Я использую GZipStream для сжатия / распаковки данных.Я выбрал это вместо DeflateStream, так как в документации говорится, что GZipStream также добавляет CRC для обнаружения поврежденных данных, что является еще одной функцией, которую я хотел.Мои «положительные» модульные тесты работают хорошо: я могу сжать некоторые данные, сохранить сжатый байтовый массив и затем снова успешно распаковать его.Пост .NET GZipStream о проблеме сжатия и распаковки помог мне понять, что мне нужно закрыть GZipStream перед доступом к сжатым или распакованным данным.
Далее я продолжил писать «отрицательный» блокпроверить, чтобы убедиться, что поврежденные данные могут быть обнаружены.Ранее я использовал пример для класса GZipStream из MSDN , чтобы сжать файл, открыть сжатый файл в текстовом редакторе, изменить байт, чтобы испортить его (как будто его не открывали в текстовом редакторе).достаточно плохо!), сохраните его, а затем распакуйте, чтобы убедиться, что я получил InvalidDataException, как и ожидалось.
Когда я написал модульный тест, я выбрал произвольный байт для повреждения (например, compressDataBytes [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 не вызвало исключение и не восстановило данные.
Я что-то упустил или сделал что-то не так?Кто-нибудь может понять, почему поврежденные сжатые данные не обнаруживаются?