Во-первых, немного информации: DEFLATE — это алгоритм сжатия, он определен в RFC 1951. DEFLATE используется в форматах ZLIB и GZIP, определенных в RFC 1950 и 1952 соответственно, которые по сути являются тонкими оболочками вокруг потоков байтов DEFLATE. Оболочки предоставляют метаданные, такие как имя файла, временные метки, CRC или Adlers и т. д.
Библиотека базовых классов .NET реализует DeflateStream, который создает необработанный поток байтов DEFLATE при использовании для сжатия. При использовании в декомпрессии он потребляет необработанный поток байтов DEFLATE. .NET также предоставляет GZipStream, который представляет собой просто оболочку GZIP вокруг этой базы. В библиотеке базовых классов .NET нет ZlibStream — ничего, что производило бы или потребляло ZLIB. Есть несколько хитростей, как это сделать, можете поискать.
Логика дефляции в .NET демонстрирует поведенческую аномалию, когда ранее сжатые данные могут быть значительно увеличены при «сжатии». Это был источник ошибка подключения, возникшая в Microsoft, и обсуждалась здесь, на SO а>. Это может быть то, что вы видите, поскольку неэффективное сжатие. Microsoft отклонила ошибку, потому что, хотя она неэффективна для экономии места, сжатый поток не является недействительным, другими словами, он может быть «распакован» любым совместимым механизмом DEFLATE.
В любом случае, как сообщил кто-то другой, сжатый поток байтов, создаваемый разными компрессорами, не обязательно может быть одинаковым. Это зависит от их настроек по умолчанию и настроек компрессора, заданных приложением. Несмотря на то, что сжатые потоки байтов различаются, они все равно могут распаковываться в один и тот же исходный поток байтов. С другой стороны, то, что вы использовали для сжатия, было GZIP, в то время как кажется, что вы хотели, это ZLIB. Хотя они связаны, они не одинаковы; вы не можете использовать GZipStream для создания потока байтов ZLIB. Это основной источник разницы, которую вы видите.
Я думаю, вам нужен поток ZLIB.
Бесплатная управляемая Zlib в проекте DotNetZip реализует сжатие потоков для всех трех форматов (DEFLATE, ZLIB, GZIP). DeflateStream и GZipStream работают так же, как встроенные классы .NET, и там есть класс ZlibStream, который делает то, что вы думаете. Ни один из этих классов не демонстрирует описанной выше аномалии поведения.
В коде это выглядит так:
byte[] original = new byte[] {
0x0E, 0x7C, 0xBD, 0x03, 0x6E, 0x65, 0x67, 0x6C,
0x65, 0x63, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x42, 0x52, 0x00, 0x00,
0x01, 0x02, 0x01, 0x00, 0xBB, 0x14, 0x8D, 0x37,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x05, 0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00
};
var compressed = Ionic.Zlib.ZlibStream.CompressBuffer(original);
Вывод такой:
0000 78 DA E3 AB D9 CB 9C 97 9A 9E 93 9A 5C C2 00 03 x...........\...
0010 4E 41 0C 0C 8C 4C 8C 0C BB 45 7A CD 61 62 AC 2F NA...L...Ez.ab./
0020 19 B0 82 46 46 2C 82 AC 40 FD 40 0A 00 35 25 07 ...FF,..@[email protected]%.
0030 CE .
Чтобы распаковать,
var uncompressed = Ionic.Zlib.ZlibStream.UncompressBuffer(compressed);
Вы можете посмотреть документацию по статическому методу CompressBuffer< /а>.
ИЗМЕНИТЬ
Возникает вопрос, почему DotNetZip выдает 78 DA
для первых двух байт вместо 78 9C
? Разница несущественная. 78 DA
кодирует "максимальное сжатие", а 78 9C
кодирует "сжатие по умолчанию". Как видно из данных, для этой небольшой выборки фактическое количество сжатых байтов точно такое же, как при использовании BEST, так и при использовании DEFAULT. Кроме того, информация об уровне сжатия не используется во время распаковки. Это не имеет никакого эффекта в вашем приложении.
Если вы не хотите "максимального" сжатия, другими словами, если вы очень настроены на получение 78 9C
в качестве первых двух байтов, даже если это не имеет значения, вы не можете использовать вспомогательную функцию CompressBuffer
, которая использует лучшее сжатие. уровень под одеялом. Вместо этого вы можете сделать это:
var compress = new Func<byte[], byte[]>( a => {
using (var ms = new System.IO.MemoryStream())
{
using (var compressor =
new Ionic.Zlib.ZlibStream( ms,
CompressionMode.Compress,
CompressionLevel.Default ))
{
compressor.Write(a,0,a.Length);
}
return ms.ToArray();
}
});
var original = new byte[] { .... };
var compressed = compress(original);
Результат:
0000 78 9C E3 AB D9 CB 9C 97 9A 9E 93 9A 5C C2 00 03 x...........\...
0010 4E 41 0C 0C 8C 4C 8C 0C BB 45 7A CD 61 62 AC 2F NA...L...Ez.ab./
0020 19 B0 82 46 46 2C 82 AC 40 FD 40 0A 00 35 25 07 ...FF,..@[email protected]%.
0030 CE .
person
Cheeso
schedule
08.06.2011