2

以下のコードを使用してファイルを圧縮しましたが、ファイルは縮小する代わりに拡大し続けます。4 kb のファイルを圧縮すると、6 になりました。これは、圧縮のオーバーヘッドのため、小さなファイルの場合は理解できます。400MBのファイルを試してみたところ、圧縮後628MBになりました。なにが問題ですか?コードを参照してください。(.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 に答える 4

4

基になるファイル自体が非常に予測不可能な場合 (既に圧縮されているか、ほとんどがランダムである場合)、圧縮しようとするとファイルが大きくなります。

deflate アルゴリズム (GZip に使用される) は最大拡張係数 0.03% に向かう傾向があるため、400 から 628Mb への拡張は拡張係数として非常にありそうにないように思えます。GZipヘッダーのオーバーヘッドは無視できるはずです。

編集: 4.0 c# リリースは、圧縮ライブラリが改善され、圧縮不可能なデータの大幅な拡張が発生しないことを示しています。これは、「生ストリーム ブロックへのフォールバック」モードを実装していなかったことを示唆しています。簡単なテストとして、SharpZipLib のライブラリを使用してみてください。これにより、デフレートによってストリームが圧縮できない場合、ほぼ同じパフォーマンスが得られるはずです。それに移行するか、よりパフォーマンスの高い BCL 実装のために 4.0 リリースを待つことを検討する場合。取得している圧縮の欠如は、とにかくさらに圧縮しようとする意味がないことを強く示唆していることに注意してください

于 2009-01-26T14:04:06.470 に答える
2

バイトごとにストリームに書き込むことが本当に良い考えですか? それは確かに理想的なパフォーマンス特性を持っていません.gzip圧縮アルゴリズムも混乱させているのかもしれません.

また、圧縮しようとしているデータが十分に圧縮できない場合もあります。私があなただったら、テキスト ドキュメントはランダム バイナリよりもはるかに圧縮率が高い傾向があるため、同じサイズのテキスト ドキュメントでコードを試してみます。

また、どちらも同じ圧縮アルゴリズム (deflate) を使用するため、GZipStream とは対照的に純粋な DeflateStream を使用してみることができます。唯一の違いは、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);
}
于 2009-01-26T14:01:19.407 に答える
1

これは、組み込みの GZipStream (および DeflateStream)の既知の異常です。
2 つの回避策が考えられます。

  • 代わりのコンプレッサーを使用してください。
  • 「圧縮された」出力のサイズを調べ、それを入力のサイズと比較するロジックを構築します。大きい場合は、出力をチャックして、データを保存するだけです。

DotNetZipには、zlib のマネージド ポートに基づく「固定」GZipStream が含まれています。(上からアプローチ#1を取ります)。Ionic.Zlib.GZipStream は、アプリの組み込み GZipStream を単純な名前空間のスワップに置き換えることができます。

于 2009-03-06T16:04:30.760 に答える
0

良い回答をありがとうございました。前に、.wmv ファイルと 1 つのテキスト ファイルを圧縮しようとしました。コードを DeflateStream に変更したところ、現在は機能しているようです。乾杯。

于 2009-01-26T14:36:21.053 に答える