0

我构思了这个想法,将任意数量的小文本文件合并到一个带有 GZipStream 类的单个 zip 文件中。我花了几个晚上让它工作,但结果是最终的 zip 文件最终比文本文件连接在一起时更大。我隐约知道霍夫曼编码是如何工作的,所以我不知道这样做是否实用,或者是否有更好的选择。最终,我想要一个外部排序索引文件来映射每个 blob 以便快速访问。你怎么看?

// keep track of index current position 
long indexByteOffset = 0;
// in reality the blobs vary in size from 1k to 300k bytes
string[] originalData = { "data blob1", "data blob2", "data blob3", "data blob4" /* etc etc etc */};
// merged compressed file
BinaryWriter zipWriter = new BinaryWriter(File.Create(@"c:\temp\merged.gz"));
// keep track of begining position and size of each blob
StreamWriter indexWriter = new StreamWriter(File.Create(@"c:\temp\index.txt")); 
foreach(var blob in originalData){
    using(MemoryStream ms = new MemoryStream()){
        using(GZipStream zipper = new GZipStream(ms, CompressionMode.Compress)){
            Encoding utf8Encoder = new UTF8Encoding();
            byte[] encodeBuffer = utf8Encoder.GetBytes(blob);
            zipper.Write(encodeBuffer, 0, encodeBuffer.Length);
        }
        byte[] compressedData = ms.ToArray();
        zipWriter.Write(compressedData);
        zipWriter.Seek(0, SeekOrigin.End);
        indexWriter.WriteLine(indexByteOffset + '\t' + (indexByteOffset + compressedData.Length));
        indexByteOffset += compressedData.Length;
    }
}
4

1 回答 1

1

不同的数据可以以不同的效果进行压缩。小数据通常不值得尝试压缩。一种常见的方法是允许“它是否被压缩?” 标志 - 进行推测压缩,但如果它更大,则存储原始压缩。该信息可以包含在索引中。不过,就我个人而言,我可能会倾向于选择一个文件——一个 .zip 文件,或者只是在每个文件之前将每个片段的长度包含为一个 4 字节块(或者可能是一个“varint”)——然后寻求第 n 个片段只是“读取长度前缀,解码为 int,寻找那么多字节,重复”的情况。您还可以保留其中的一部分用于“是否已压缩”。

但至于“是否值得压缩”:这取决于您的数据。

于 2012-11-30T09:43:48.970 回答