base64 - ファイルをエンコードして圧縮します
-
13-12-2019 - |
質問
私の目標は、ファイルをエンコードしてそれをJavaのフォルダにZipすることです。ApacheのCommons-Codecライブラリを使用する必要があります。私はそれを符号化してzipすることができて、それはうまく機能しますが、それを元の形に復号すると、ファイルが完全にエンコードされていないように見えます。いくつかの部分が欠けているように見えます。誰かがなぜこれが起こるのか教えてもらえますか?
私はあなたの参照のために私のコードの一部を添付していますので、それに応じて私を導くことができるようにしています。
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();
}
}
. 解決
Base64エンコードされたデータは通常ソースよりも長いですが、出力ストリームにエンコードされた書き込みにソースデータの長さを使用しています。
変数len
ではなく、生成された配列のサイズを使用しています。
2番目の通知 - バイトをエンコードするたびにbuffer
を再定義しないでください。結果を出力に書き込むだけです。
while ((len = in.read(buffer)) > 0) {
byte [] enc = Base64.encodeBase64(Arrays.copyOf(buffer, len));
out.write(enc, 0, enc.length);
}
.
update: arriay.copyof(...)
の入力バッファの長さを設定する。他のヒント
あなたの主な問題は、base64エンコーディングをブロック単位で適用できないことです(特にApache-Commons実装ではありません)。この問題は、ブロックがin.read(..)
によって読み込まれたバイト数によってどのような大きさがあるかを知らないので、この問題は悪化しています。
それゆえあなたは2つの選択肢を持っています:
- 完全なファイルをメモリにロードしてから、Base64エンコードを適用します。
- Stream-Baseを作品する代替Base64エンコーダの実装を使用する(Apache Batikプロジェクトはそのような実装を含めるように思われる:
org.apache.batik.util.base64encoderStream )
ファイルの内容を buffer に読み込むときは、 len バイトになります。これをencodingこれをエンコードするときは、 len バイトを超えていますが、まだ len バイトをファイルに書き込むだけです。読み込んだチャンクの最後の部分が切り捨てられるようになるこのBean。
また、読み取りがバッファ全体を埋めていない場合は、最後のバイトのパディングで0が末尾に0を末尾に入手するため、Base64を LEN バイトを符号化しないでください。
これを上記の情報を組み合わせる必要があることは、読み取られた各チャンクがBase64エンコードされたメッセージに正確に適合できることを保証することができない限り、Base64をファイル全体にエンコードする必要があることを意味します。ファイルがあまり大きくない場合は、ファイル全体を読むことをお勧めします。
問題が小さいほど、ループを読み込むときは「> 0」ではなく「> -1」をチェックする必要があることは、違いは違いはありません。