Файл, сжатый GZIP, растет, а не сжимается - PullRequest
2 голосов
/ 26 января 2009

Я использовал приведенный ниже код для сжатия файлов, и они продолжают расти, а не сжиматься. Я сжал файл 4 Кбайт, и он стал 6. Это понятно для небольшого файла из-за сжатия сжатия. Я попытался файл 400 МБ, и после сжатия он стал 628 МБ. Что случилось? Смотрите код. (.net 2.0)

Public Sub Compress(ByVal infile As String, ByVal outfile As String)
    Dim sourceFile As FileStream = File.OpenRead(inFile)
    Dim destFile As FileStream = File.Create(outfile)

    Dim compStream As New GZipStream(destFile, CompressionMode.Compress)

    Dim myByte As Integer = sourceFile.ReadByte()
    While myByte <> -1
        compStream.WriteByte(CType(myByte, Byte))
        myByte = sourceFile.ReadByte()
    End While

    sourceFile.Close()
    destFile.Close()
End Sub

Ответы [ 4 ]

4 голосов
/ 26 января 2009

Если базовый файл сам по себе крайне непредсказуем (уже сжат или в значительной степени случайный), то попытка сжать его приведет к увеличению размера файла.

Переход от 400 до 628 МБ звучит крайне маловероятно в качестве коэффициента расширения, поскольку алгоритм дефляции (используемый для GZip) стремится к максимальному коэффициенту расширения , равному 0,03% Издержки заголовка GZip должны быть незначительными. 1005 *

Edit: версия 4.0 c # указывает, что библиотеки сжатия были улучшены, чтобы не вызывать значительного расширения несжимаемых данных. Это говорит о том, что они не реализовывали режим «откат к необработанным потоковым блокам». Попробуйте использовать библиотеку SharpZipLib в качестве быстрого теста. Это должно обеспечить вам практически одинаковую производительность, когда поток сжимается с помощью deflate. Если это действительно переходит к этому или ждет выпуска 4.0 для более производительной реализации BCL. Обратите внимание, что отсутствие сжатия, которое вы получаете, говорит о том, что нет смысла пытаться продолжать сжатие в любом случае

2 голосов
/ 26 января 2009

Вы уверены, что запись байта в поток - действительно хорошая идея? Конечно, он не будет иметь идеальных характеристик производительности, и, возможно, именно это смущает алгоритм сжатия gzip.

Также может случиться, что данные, которые вы пытаетесь сжать, просто не очень хорошо сжимаются. На вашем месте я бы попробовал ваш код с текстовым документом того же размера, что и текстовые документы, как правило, сжимается намного лучше, чем произвольный двоичный файл.

Кроме того, вы можете попробовать использовать чистый DeflateStream в отличие от GZipStream, так как они оба используют один и тот же алгоритм сжатия (deflate), единственное отличие состоит в том, что gzip добавляет некоторые дополнительные данные (например, проверку ошибок), так что DeflateStream может привести к меньшему результаты.

Мой VB.NET немного заржавел, поэтому я не буду пытаться писать пример кода в VB.NET. Вместо этого, вот как вы должны сделать это в C #, это должно быть относительно просто, чтобы перевести его на VB.NET для кого-то с небольшим опытом: (или, может быть, кто-то, кто хорош в VB.NET, может отредактировать мой пост и перевести его на VB.NET)

FileStream sourceFile;
GZipStream compStream;

byte[] buffer = new byte[65536];
int bytesRead = 0;
while (bytesRead = sourceFile.Read(buffer, 0, 65536) > 0)
{
     compStream.Write(buffer, 0, bytesRead);
}
1 голос
/ 06 марта 2009

Это известная аномалия со встроенным GZipStream (и DeflateStream).
Я могу придумать два обходных пути:

  • используйте альтернативный компрессор.
  • построить некоторую логику, которая проверяет размер «сжатого» вывода и сравнивает его с размером ввода. Если больше, бросьте вывод и просто сохраните данные.

DotNetZip включает в себя «фиксированный» GZipStream на основе управляемого порта zlib. (Требуется подход № 1 сверху). Ionic.Zlib.GZipStream может заменить встроенный GZipStream в ваших приложениях простым обменом пространства имен.

0 голосов
/ 26 января 2009

Спасибо всем за хорошие ответы. Ранее я пытался сжать файлы .wmv и один текстовый файл. Я изменил код на DeflateStream, и теперь он работает. Приветствия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...