5

私の目標は、ファイルをエンコードし、Java のフォルダーに圧縮することです。Apache の Commons-codec ライブラリを使用する必要があります。エンコードして圧縮することができ、正常に動作しますが、デコードして元の形式に戻すと、ファイルが完全にエンコードされていないように見えます。いくつかの部品が欠落しているようです。なぜこれが起こるのか誰か教えてもらえますか?

また、参照用にコードの一部を添付して、それに応じてガイドできるようにします。

private void zip() {
    int BUFFER_SIZE = 4096;
    byte[] buffer = new byte[BUFFER_SIZE];

    try {
        // Create the ZIP file
        String outFilename = "H:\\OUTPUT.zip";
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
                outFilename));

        // Compress the files
        for (int i : list.getSelectedIndices()) {
            System.out.println(vector.elementAt(i));
            FileInputStream in = new FileInputStream(vector.elementAt(i));
            File f = vector.elementAt(i);

            // Add ZIP entry to output stream.
            out.putNextEntry(new ZipEntry(f.getName()));

            // Transfer bytes from the file to the ZIP file
            int len;

            while ((len = in.read(buffer)) > 0) {
                buffer = org.apache.commons.codec.binary.Base64
                        .encodeBase64(buffer);
                out.write(buffer, 0, len);

            }

            // Complete the entry
            out.closeEntry();
            in.close();

        }

        // Complete the ZIP file
        out.close();
    } catch (IOException e) {
        System.out.println("caught exception");
        e.printStackTrace();
    }
}
4

3 に答える 3

3

通常、BASE64 でエンコードされたデータはソースよりも長くなりますが、ソース データの長さを使用して、エンコードされたデータを出力ストリームに書き込みます。

変数の代わりに、生成された配列のサイズを使用していますlen

buffer再通知 -バイトをエンコードするたびに再定義しないでください。結果を出力に書き込むだけです。

 while ((len = in.read(buffer)) > 0)  {                         
     byte [] enc = Base64.encodeBase64(Arrays.copyOf(buffer, len));
     out.write(enc, 0, enc.length);
 }

更新: Arrays.copyOf(...)を使用して、エンコード用の入力バッファーの長さを設定します。

于 2012-03-13T09:34:55.437 に答える
0

ファイルの内容をバッファに読み込むと、 lenバイトが取得されます。これを base64 でエンコードすると、 lenバイトを超える値が得られますが、ファイルにはlenバイトしか書き込まれません。この Bean は、読み取りチャンクの最後の部分が切り捨てられます。

また、読み取りでバッファ全体がいっぱいにならない場合は、最後のバイトのパディングで後続の 0 が取得されるため、 lenバイトを超えて base64 エンコードしないでください。

上記の情報を組み合わせると、読み取る各チャンクが base64 エンコードされたメッセージに正確に収まることを保証できない限り、ファイル全体を base64 エンコードする (すべてを byte[] に読み取る) 必要があることを意味します。ファイルがそれほど大きくない場合は、ファイル全体を読むことをお勧めします。

より小さな問題は、ループを読み取るときに、おそらく "> 0" ではなく "> -1" をチェックする必要があることですが、彼の場合は違いはありません。

于 2012-03-13T09:36:55.423 に答える
0

あなたの主な問題は、base64エンコーディングをブロック単位で適用できないことです(特にapache-commonsの実装ではありません)。これは によって読み取られるバイト数に依存するため、ブロックの大きさがわからないため、この問題は悪化していますin.read(..)

したがって、次の 2 つの選択肢があります。

  1. 完全なファイルをメモリにロードしてから、base64 エンコーディングを適用します。
  2. ストリームベースで動作する別の Base64 エンコーダー実装を使用します (Apache Batik プロジェクトにはそのような実装が含まれているようです: org.apache.batik.util.Base64EncoderStream )
于 2012-03-13T09:32:47.523 に答える