System.IO.Compression.GZipStreamまたはSystem.IO.Compression.Deflateはzlib圧縮と互換性がありますか?
8 に答える
Git オブジェクトでこの問題に遭遇しました。その特定のケースでは、 RFC 1950で文書化されている Zlib ヘッダーを使用して、収縮した blob としてオブジェクトを格納します。以下を含むファイルを作成することで、互換性のある BLOB を作成できます。
- 値を持つ 2 つのヘッダー バイト (RFC 1950 の CMF および FLG)
0x78 0x01
CM
= 8 = 空気を抜くCINFO
= 7 = 32Kb ウィンドウFCHECK
= 1 = このヘッダーのチェックサム ビット
- C# の出力
DeflateStream
DeflateStream
ビッグエンディアン形式 (MSB ファースト)への入力データの Adler32 チェックサム
独自の Adler 実装を作成しました
public class Adler32Computer
{
private int a = 1;
private int b = 0;
public int Checksum
{
get
{
return ((b * 65536) + a);
}
}
private static readonly int Modulus = 65521;
public void Update(byte[] data, int offset, int length)
{
for (int counter = 0; counter < length; ++counter)
{
a = (a + (data[offset + counter])) % Modulus;
b = (b + a) % Modulus;
}
}
}
そして、それはほとんどそれでした。
DotNetZipには、RFC 1950、1951、および 1952 を処理するための DeflateStream、ZlibStream、および GZipStream が含まれています。これらはすべて DEFLATE アルゴリズムを使用しますが、フレーミングとヘッダー バイトはそれぞれ異なります。
利点として、DotNetZip のストリームは、ビルトイン ストリームに対して報告された、圧縮下でのデータ サイズの拡大の異常を示しません。また、組み込みの ZlibStream はありませんが、DotNetZip は zlib との良好な相互運用性のためにそれを提供します。
System.IO.Compression.GZipStream に関するMSDNから:
このクラスは、業界標準のアルゴリズムを使用してロスレス ファイル圧縮および圧縮解除を行う gzip データ形式を表します。
zlib FAQから:
一方、zlib の gz* 関数は gzip 形式を使用します。
したがって、zlib と GZipStream は相互運用可能である必要がありますが、gzip 形式を処理するために zlib 関数を使用する場合に限られます。
System.IO.Compression.Deflate と zlib は相互運用性がないと報告されています。
zip ファイルを処理する必要がある場合 (おそらく必要ありませんが、他の誰かがこれを必要とする場合があります)、SharpZipLibまたは別のサードパーティ ライブラリを使用する必要があります。
GZipStreamを使用して.NETXmlSerializerからの出力を圧縮しましたが、gunzip(cygwin内)、winzip、および別のGZipStreamを使用して結果を解凍することは完全に正常に機能しました。
参考までに、コードで行ったことは次のとおりです。
FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write);
using (GZipStream gzStream = new GZipStream(fs, CompressionMode.Compress))
{
XmlSerializer serializer = new XmlSerializer(typeof(MyDataType));
serializer.Serialize(gzStream, myData);
}
次に、C#で解凍します
FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
using (Stream input = new GZipStream(fs, CompressionMode.Decompress))
{
XmlSerializer serializer = new XmlSerializer(typeof(MyDataType));
myData = (MyDataType) serializer.Deserialize(input);
}
cygwinで「file」ユーティリティを使用すると、GZipStreamとGNU GZipで圧縮された同じファイル(おそらく他の人がこのスレッドで述べているようにヘッダー情報)の間に実際に違いがあることがわかります。ただし、この違いは実際には問題ではないようです。
gzip は deflate + チェックサムや長さなどの一部のヘッダー/フッター データです。そのため、一方のメソッドが他方のストリームを使用できるという意味では互換性がありませんが、同じ圧縮アルゴリズムを採用しています。
zlibまたはdeflateアルゴリズムを使用してデータを圧縮するだけですが、特定のファイル形式の出力は提供しません。つまり、ストリームをそのままハードドライブに保存すると、ファイルヘッダー(マジックナンバーなど)がストリームに含まれていないため、アプリケーション(gzipまたはwinrar)を使用してストリームを開くことができない可能性があります。それらを自分で書いてください。
.NET Framework 4.5 以降、System.IO.Compression.DeflateStream
クラスは zlib ライブラリを使用します。
クラスのMSDNの記事から:
このクラスは、ロスレス ファイル圧縮および圧縮解除の業界標準アルゴリズムである Deflate アルゴリズムを表します。.NET Framework 4.5 以降、DeflateStream クラスは zlib ライブラリを使用します。その結果、より優れた圧縮アルゴリズムが提供され、ほとんどの場合、以前のバージョンの .NET Framework よりも小さい圧縮ファイルが提供されます。
私はアンドレアスに同意します。おそらく、外部ツールでファイルを開くことはできませんが、そのツールがストリームを想定している場合は、それを使用できる可能性があります。同じ圧縮クラスを使用して、ファイルを元に戻すこともできます。