Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用由0和1组成的数据实现最佳压缩?_C#_Compression - Fatal编程技术网

C# 使用由0和1组成的数据实现最佳压缩?

C# 使用由0和1组成的数据实现最佳压缩?,c#,compression,C#,Compression,我正试图为矩阵中仅包含1和0的数据实现尽可能最好的压缩 为了证明我的意思,这里有一个6×6矩阵示例: 1,0,0,1,1,1 0,1,0,1,1,1 1,0,0,1,0,0 0,1,1,0,1,1 1,0,0,0,0,1 0,1,0,1,0,1 我想把它压缩成尽可能小的字符串或字节数组。我需要压缩的矩阵更大(总是4096乘40961s和0s) 我想它可能会被压缩得很重,但我不知道怎么压缩。我将标记最佳压缩作为答案。性能并不重要。尝试创建自己的算法来专门压缩这些数据很可能不会产生太多效果 Cre

我正试图为矩阵中仅包含1和0的数据实现尽可能最好的压缩

为了证明我的意思,这里有一个6×6矩阵示例:

1,0,0,1,1,1
0,1,0,1,1,1
1,0,0,1,0,0
0,1,1,0,1,1
1,0,0,0,0,1
0,1,0,1,0,1
我想把它压缩成尽可能小的字符串或字节数组。我需要压缩的矩阵更大(总是4096乘40961s和0s)


我想它可能会被压缩得很重,但我不知道怎么压缩。我将标记最佳压缩作为答案。性能并不重要。

尝试创建自己的算法来专门压缩这些数据很可能不会产生太多效果

Create a GZipStream with Max CompressionLevel
Run a 4096x4096 loop
 - set all 64 bits of a ulong to bits of the array
 - when 64 bits are done write the ulong to the compressionstream and start at the first bit again

这将非常容易地将多维数据集添加到一个相当压缩的内存块中

嗯。。。在不了解问题域的情况下,尽可能小是不可能的

以下是一般方法:

  • 用位表示数组中的1和0,而不是字节或字符或其他
  • 使用通用的无损耗压缩算法进行压缩。最常见的两种是: 哈夫曼编码和某些类型的LZW 哈夫曼可以从数学上证明提供最好的数据压缩,关键是要解压数据,还需要哈夫曼树,它可能与原始数据一样大。LZW为大多数输入提供了与哈夫曼(Huffman)相当的压缩(在几个百分比之内),但对具有重复段(如文本)的数据的压缩效果最好。 压缩算法的实现应该很容易获得(GZIP使用LZ77,它是LZW的一个稍不理想的早期版本)

    使用现代算法的压缩算法的良好实现请访问7zip.org。它是开源的,他们有一个带有DLL的C API,但是你必须创建.Net接口(除非有人已经创建了一个)

    非一般性办法: 这取决于数据的已知特征。例如:如果您知道大多数数据是零,那么您只能对一的坐标进行编码。 如果数据包含1和0的补丁,则可以使用RLE或算法的二维变体对其进行编码。

    使用可以对其进行大量压缩:

    0  => 111
    1  => 10
    ,  => 0
    \r => 1100
    \n => 1101
    
    示例矩阵的收益率(以位为单位):

    如果可以排除逗号、换行符和回车符,则只需要一个字符来存储每个值。虽然现在你需要知道解码时矩阵的维数。如果不这样做,则可以将其存储为int,如果计划序列化数据,则可以将其存储为数据本身

    比如:

    var input = @"1,0,0,1,1,1
                  0,1,0,1,1,1
                  1,0,0,1,0,0
                  0,1,1,0,1,1
                  1,0,0,0,0,1
                  0,1,0,1,0,1";
    
    var values = new List<bool>();
    foreach(var c in input)
    {
      if (c == '0')
        values.Add(false);
      else if (c == '1')
        values.Add(true);
    }
    
    var ba = new BitArray(values.ToArray());
    
    var输入=@“1,0,0,1,1,1
    0,1,0,1,1,1
    1,0,0,1,0,0
    0,1,1,0,1,1
    1,0,0,0,0,1
    0,1,0,1,0,1";
    var值=新列表();
    foreach(输入中的var c)
    {
    如果(c=='0')
    值。添加(false);
    else如果(c=='1')
    值。添加(true);
    }
    var ba=新的位数组(values.ToArray());
    
    然后序列化位数组。您可能需要添加一些填充位来正确解码数据。(4096*4096可被8整除)


    除非矩阵中有大量重复模式(是的,我假设数据大部分是随机的),否则BitArray方法应该可以获得最大的压缩。

    我假设您希望将字符串压缩为其他字符串,即使您的数据实际上是二进制的。我不知道最好的压缩算法是什么(这取决于您的数据),但您可以将输入文本转换为位,压缩这些位,然后再次使用base-64编码将压缩的字节转换为字符串。这将允许您从一个字符串切换到另一个字符串,并且仍然应用您选择的压缩算法

    NET framework提供了一个类,允许您压缩字节流。第一步是创建一个自定义的
    ,允许您读写文本格式。由于没有更好的名字,我把它命名为
    TextStream
    。请注意,为了简化一些问题,我使用
    \n
    作为行结尾(而不是
    \r\n

    为了测试它,我使用了一种方法创建了一个随机字符串(使用固定种子始终创建相同的字符串):

    String CreateRandomString(Int32宽度,Int32高度){
    var random=新随机数(0);
    var stringBuilder=新的stringBuilder();
    对于(变量i=0;i0&&j==0)
    stringBuilder.Append('\n');
    否则,如果(j>0)
    追加(',');
    stringBuilder.Append(random.Next(2)=0?'0':'1');
    }
    }
    返回stringBuilder.ToString();
    }
    
    创建随机4096 x 4096字符串的未压缩大小为33554431个字符。这是压缩到2797056个字符,这是一个减少到约8%的原始大小

    跳过base-64编码将进一步提高压缩比,但输出将是二进制而不是字符串。如果你还把输入看作二进制,实际上你得到的结果等于0和1的随机数据:

    Input bytes: 4,096 x 4,096 / 8 = 2,097,152 Output bytes: 2,097,792 Size after compression: 100% 输入字节:4096 x 4096/8=2097152 输出字节:2097792 压缩后尺寸:100% 简单地转换成字节要比通过一个deflate来转换好。但是,使用随机输入,但使用25%0和75%1,您会得到以下结果:

    Input bytes: 4,096 x 4,096 / 8 = 2,097,152 Output bytes: 1,757,846 Size after compression: 84% 输入字节:4096 x 4096/8=2097152 输出字节:1757846 压缩后尺寸:84%
    多少deflate将压缩您的数据实际上取决于数据的性质。如果是完全随机的,在将文本转换为字节后,您将无法获得太多的压缩。

    先将它们压缩为位,然后对生成的位应用任何好的压缩算法如何?然后必须压缩2MB的随机字节。可能适合你。最终结果必须是字符串吗<代码>字节[]更有意义。字节是
    String Compress(String text) {
      using (var inputStream = new TextStream(text))
        using (var outputStream = new MemoryStream()) {
          using (var compressedStream = new DeflateStream(outputStream, CompressionMode.Compress))
            inputStream.CopyTo(compressedStream);
          return Convert.ToBase64String(outputStream.ToArray());
        }
    }
    
    String Decompress(String compressedText, Int32 bitsPerLine) {
      var bytes = Convert.FromBase64String(compressedText);
      using (var inputStream = new MemoryStream(bytes))
        using (var outputStream = new TextStream(bitsPerLine)) {
          using (var compressedStream = new DeflateStream(inputStream, CompressionMode.Decompress))
            compressedStream.CopyTo(outputStream);
          return outputStream.ToString();
        }
    }
    
    String CreateRandomString(Int32 width, Int32 height) {
      var random = new Random(0);
      var stringBuilder = new StringBuilder();
      for (var i = 0; i < width; ++i) {
        for (var j = 0; j < height; ++j) {
          if (i > 0 && j == 0)
            stringBuilder.Append('\n');
          else if (j > 0)
            stringBuilder.Append(',');
          stringBuilder.Append(random.Next(2) == 0 ? '0' : '1');
        }
      }
      return stringBuilder.ToString();
    }
    
    Input bytes: 4,096 x 4,096 / 8 = 2,097,152 Output bytes: 2,097,792 Size after compression: 100% Input bytes: 4,096 x 4,096 / 8 = 2,097,152 Output bytes: 1,757,846 Size after compression: 84%