Во-первых, некоторая информация: DEFLATE - алгоритм сжатия, он определен в RFC 1951 .DEFLATE используется в форматах ZLIB и GZIP, определенных в RFC 1950 и 1952 соответственно, которые, по сути, являются тонкими обертками вокруг потоков потока DEFLATE.Оболочки предоставляют метаданные, такие как имя файла, метки времени, CRC или Adlers и т. Д.
. Библиотека базовых классов .NET реализует DeflateStream, который генерирует необработанный поток DEFLATE при использовании для сжатия.При использовании в декомпрессии он потребляет необработанный поток DEFLATE..NET также предоставляет GZipStream, который является просто оболочкой GZIP вокруг этой базы.В библиотеке базовых классов .NET нет ZlibStream - ничего, что создает или потребляет ZLIB.Есть некоторые хитрости, чтобы сделать это, вы можете искать вокруг.
Логика дефляции в .NET демонстрирует поведенческую аномалию, при которой ранее сжатые данные могут быть значительно раздуты, значительно при «сжатии».Это было источником ошибки Connect, возникшей в 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,..@.@..5%.
0030 CE .
Для распаковки,
var uncompressed = Ionic.Zlib.ZlibStream.UncompressBuffer(compressed);
Вы можете увидеть документацию по статическому методу CompressBuffer .
РЕДАКТИРОВАТЬ
Возникает вопрос, почемуDotNetZip производит 78 DA
для первых двух байтов вместо 78 9C
?Разница несущественна.78 DA
кодирует «максимальное сжатие», а 78 9C
кодирует «сжатие по умолчанию».Как видно из данных, для этого небольшого примера фактические сжатые байты в точности совпадают при использовании BEST или DEFAULT.Кроме того, информация об уровне сжатия не используется во время распаковки.Это не влияет на ваше приложение.
Если вам не нужно сжатие "max", другими словами, если вы очень сильно хотите получить 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,..@.@..5%.
0030 CE .