Почему сжатие gzip / deflate небольшого файла приводит ко многим конечным нулям?

#c# #compression #gzip

#c# #сжатие #gzip

Вопрос:

Я использую следующий код для сжатия небольшого (~ 4 КБ) HTML-файла в C #.

 byte[] fileBuffer = ReadFully(inFile, ResponsePacket.maxResponsePayloadLength); // Read the entire requested HTML file into a memory buffer
inFile.Close();                                                                 // Close the requested HTML file

byte[] payload;
using (MemoryStream compMS = new MemoryStream())                                       // Create a new memory stream to hold the compressed HTML data
{
    using (GZipStream gzip = new GZipStream(compMS, CompressionMode.Compress))            // Create a new GZip object pointing to the empty memory stream
    {
        gzip.Write(fileBuffer, 0, fileBuffer.Length);                                   // Compress the file buffer and write it to the empty memory stream
        gzip.Close();                                                                   // Close the GZip object
    }
    payload = compMS.GetBuffer();                                            // Write the compressed file buffer data in the memory stream to a byte buffer
}
  

Результирующие сжатые данные составляют около 2 кб, но примерно половина из них — это просто нули. Это для приложения, очень чувствительного к пропускной способности (именно поэтому я в первую очередь беспокоюсь о сжатии 4 КБ), поэтому лишний 1 КБ нулей тратится впустую на ценное пространство. Мое лучшее предположение заключается в том, что алгоритм сжатия выводит данные до границы блока. Если да, есть ли какой-либо способ переопределить это поведение или изменить размер блока? Я получаю те же результаты с помощью ванильного .NET GZipStream и zlib GZipStream, а также DeflateStream.

Ответ №1:

Неправильный метод MemoryStream. GetBuffer() возвращает базовый буфер, он всегда больше (или точно такой же большой), как данные в потоке. Очень эффективно, потому что не нужно делать копию.

Но здесь вам нужен метод toArray(). Или используйте свойство Length.