0

GZipStream クラスを使用して、任意の数の小さなテキスト ファイルを 1 つの 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

データが異なれば、圧縮の効果も異なります。通常、小さなデータは圧縮しようとする価値はありません。一般的なアプローチの 1 つは、「圧縮されているかどうか」を確認することです。フラグ - 投機的圧縮を行いますが、サイズが大きい場合は元を保存します。その情報をインデックスに含めることができます。ただし、個人的には、.zip か、各フラグメントの長さを 4 バイトのチャンク (または「varint」) として各フラグメントの前に含めるかのいずれかの単一のファイルを使用するように誘惑される可能性があります n 番目のフラグメントは、「長さのプレフィックスを読み取り、int としてデコードし、そのバイト数をシークし、繰り返す」場合にすぎません。その 1 ビットを「圧縮されているか」用に予約することもできます。

しかし、「圧縮する価値があるか」については、データによって異なります。

于 2012-11-30T09:43:48.970 に答える