Java と Go で Gzip 圧縮が異なるのはなぜですか?
Java と Go で gzip を使用してデータを圧縮すると、異なる結果が発生する可能性があります。この相違は、データ表現と圧縮実装の根本的な違いに起因します。
バイト表現
Java のバイト型は、-128 から 127 の範囲で符号付きです。Go では、 byte 型は uint8 のエイリアスで、0 ~ 255 の符号なし整数を表します。これは、負の値が含まれることを意味します。 Go のバイト範囲に一致させるには、Java を 256 シフトする必要があります。
圧縮の違い
バイト表現を考慮した後でも、圧縮結果は Java と Go で異なる場合があります。 。 LZ77 およびハフマンコーディングを使用する gzip アルゴリズムは、入力文字の頻度に影響されます。文字の頻度が異なると、出力コードやビット パターンが異なる場合があります。
さらに、実装が異なれば、デフォルトの圧縮レベルも異なる場合があります。 Java と Go はどちらも名目上デフォルト レベル 6 を使用しますが、実装におけるわずかな違いが残りの違いを説明する可能性があります。
同様の出力の達成
これらの違いを排除して取得するにはgzip 出力を一致させると、両方の言語で圧縮レベルを 0 に設定できます。 Java は Deflater.NO_COMPRESSION オプションを提供し、Go は gzip.NoCompression を提供します。
Java コードの例:
ByteArrayOutputStream buf = new ByteArrayOutputStream(); GZIPOutputStream gz = new GZIPOutputStream(buf) { { def.setLevel(Deflater.NO_COMPRESSION); } }; gz.write("helloworld".getBytes("UTF-8")); gz.close(); for (byte b : buf.toByteArray()) System.out.print((b & 0xff) + " ");
Go コードの例:
var buf bytes.Buffer gz, _ := gzip.NewWriterLevel(&buf, gzip.NoCompression) gz.Write([]byte("helloworld")) gz.Close() fmt.Println(buf.Bytes())
ヘッダーフィールド
gzip には、変更時刻やファイル名などのオプションのヘッダー フィールドが含まれていることは注目に値します。 Java はデフォルトでこれらのフィールドを追加しませんが、Go は追加します。したがって、同じ圧縮レベルであっても、これらの追加ヘッダーのせいで正確な出力が得られない可能性があります。
実際的な考慮事項
ただし、圧縮された出力は Java 間で一致しない可能性があります。および Go の場合でも、互換性のある gzip デコーダを使用してデータを解凍できます。解凍されたデータは、圧縮の実装に関係なく同一になります。したがって、出力の違いは実質的に重要ではありません。
以上がJava と Go で異なる GZIP 圧縮結果が生成されるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。