Потоки сжатия, совместимые с Zlib?
-
09-06-2019 - |
Вопрос
Совместимы ли System.IO.Compression.GZipStream или System.IO.Compression.Deflate со сжатием zlib?
Решение
От MSDN о System.IO.Compression.GZipStream:
Этот класс представляет формат данных gzip, который использует стандартный отраслевой алгоритм сжатия и распаковки файлов без потерь.
Из самого часто задаваемые вопросы по zlib:
С другой стороны, функции gz * в zlib используют формат gzip.
Таким образом, zlib и GZipStream должны быть совместимы, но только если вы используете функции zlib для обработки формата gzip.
System.IO.Compression.Как сообщается, Deflate и zlib несовместимы.
Если вам нужно обрабатывать zip-файлы (вероятно, у вас их нет, но это может понадобиться кому-то другому), вам нужно использовать Острый зажим или другая сторонняя библиотека.
Другие советы
DotNetZip - файл включает DeflateStream, ZlibStream и GZipStream для обработки RFC 1950, 1951 и 1952.Все они используют алгоритм DEFLATE, но байты кадрирования и заголовка различны для каждого из них.
В качестве преимущества потоки в DotNetZip не демонстрируют аномалия увеличения размера данных находится в состоянии сжатия, сопоставляется со встроенными потоками.Кроме того, нет встроенного ZlibStream, тогда как DotNetZip предоставляет вам это для хорошего взаимодействия с zlib.
Я столкнулся с этой проблемой с объектами Git.В этом конкретном случае они сохраняют объекты в виде спущенных больших двоичных объектов с заголовком Zlib, который задокументирован в RFC 1950.Вы можете создать совместимый большой двоичный объект, создав файл, содержащий:
- Два байта заголовка (CMF и FLG из RFC 1950) со значениями
0x78 0x01
CM
= 8 = сдутьCINFO
Окно = 7 = 32 КБFCHECK
= 1 = биты контрольной суммы для этого заголовка .
- Результат работы C#
DeflateStream
- Контрольная сумма Adler32 входных данных для
DeflateStream
, формат big-endian (сначала MSB)
Я создал свою собственную реализацию 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;
}
}
}
И это было в значительной степени все.
Я использовал GZipStream для сжатия выходных данных из .NET XmlSerializer, и он отлично справился с распаковкой результата с помощью 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);
}
Использование утилиты "file" в cygwin показывает, что действительно существует разница между одним и тем же файлом, сжатым с помощью 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.
Я согласен с Андреасом.Вероятно, вы не сможете открыть файл с помощью внешнего инструмента, но если этот инструмент ожидает поток, вы, возможно, сможете его использовать.Вы также сможете выкачать файл обратно, используя тот же класс сжатия.