GZipStream を使用してデータを圧縮/解凍しています。ドキュメンテーションには、GZipStream が破損したデータを検出するための CRC も追加すると記載されているため、DeflateStream よりもこれを選択しました。これは、私が欲しかったもう 1 つの機能です。私の「肯定的な」単体テストは、一部のデータを圧縮し、圧縮されたバイト配列を保存してから、再び正常に解凍できるという点でうまく機能しています。.NET GZipStreamの圧縮と解凍に関する問題の投稿は、圧縮または解凍されたデータにアクセスする前に GZipStream を閉じる必要があることに気付きました。
次に、破損したデータを検出できることを確認するために、引き続き "ネガティブ" 単体テストを作成しました。以前、MSDN の GZipStream クラスの例を使用してファイルを圧縮し、圧縮ファイルをテキスト エディターで開き、1 バイトを変更してファイルを破損させました (テキスト エディターで開くだけでは不十分であるかのように!)。それを解凍して、期待どおりに InvalidDataException が発生したことを確認します。
単体テストを作成したとき、破損する任意のバイト (たとえば、compressedDataBytes[50] = 0x99) を選択し、InvalidDataException を取得しました。ここまでは順調ですね。気になったので、別のバイトを選んだのですが、驚いたことに、例外は発生しませんでした。データが正常に復元される限り、これは問題ない可能性があります (たとえば、データ ブロック内の未使用のバイトに偶然ヒットした場合など)。ただし、正しいデータも返されませんでした。
「私ではなかった」ことを確認するために、.NET GZipStream の圧縮と解凍の問題の下部からクリーンアップされたコードを取得し、適切に解凍できなくなるまで圧縮データの各バイトを順次破損するように修正しました。変更点は次のとおりです (Visual Studio 2010 テスト フレームワークを使用していることに注意してください)。
// successful compress / decompress example code from:
// https://stackoverflow.com/questions/1590846/net-gzipstream-compress-and-decompress-problem
[TestMethod]
public void Test_zipping_with_memorystream_and_corrupting_compressed_data()
{
const string sample = "This is a compression test of microsoft .net gzip compression method and decompression methods";
var encoding = new ASCIIEncoding();
var data = encoding.GetBytes(sample);
string sampleOut = null;
byte[] cmpData;
// Compress
using (var cmpStream = new MemoryStream())
{
using (var hgs = new GZipStream(cmpStream, CompressionMode.Compress))
{
hgs.Write(data, 0, data.Length);
}
cmpData = cmpStream.ToArray();
}
int corruptBytesNotDetected = 0;
// corrupt data byte by byte
for (var byteToCorrupt = 0; byteToCorrupt < cmpData.Length; byteToCorrupt++)
{
// corrupt the data
cmpData[byteToCorrupt]++;
using (var decomStream = new MemoryStream(cmpData))
{
using (var hgs = new GZipStream(decomStream, CompressionMode.Decompress))
{
using (var reader = new StreamReader(hgs))
{
try
{
sampleOut = reader.ReadToEnd();
// if we get here, the corrupt data was not detected by GZipStream
// ... okay so long as the correct data is extracted
corruptBytesNotDetected++;
var message = string.Format("ByteCorrupted = {0}, CorruptBytesNotDetected = {1}",
byteToCorrupt, corruptBytesNotDetected);
Assert.IsNotNull(sampleOut, message);
Assert.AreEqual(sample, sampleOut, message);
}
catch(InvalidDataException)
{
// data was corrupted, so we expect to get here
}
}
}
}
// restore the data
cmpData[byteToCorrupt]--;
}
}
このテストを実行すると、次のようになります。
Assert.AreEqual failed. Expected:<This is a compression test of microsoft .net gzip compression method and decompression methods>. Actual:<>. ByteCorrupted = 11, CorruptBytesNotDetected = 8
したがって、これは実際には、データを破損しても違いがなかった (文字列が正常に復元された) 7 つのケースがあったことを意味しますが、バイト 11 を破損しても例外はスローされず、データも復元されませんでした。
私は何かを見逃していますか、何か間違っていますか? 破損した圧縮データが検出されない理由を誰でも確認できますか?