Base64InputStream
興味深いことに、ここでいくつかのテストを行いました。ストリームのソースに関係なく、を使用して読み取ると、実際にその例外がスローされますがInputStreamReader
、バイナリストリームとして読み取ると問題なく動作します。Trashgodが述べたように、Base64エンコーディングはフレーム化されています。は、実際には、それ以上データが返されないかどうかを確認するためにもう一度InputStreamReader
呼び出しflush()
ているはずです。Base64InputStream
Base64InputStreamReader
独自のまたはを実装する以外に、これを修正する方法はありませんBase64Reader
。これは実際にはバグです。キースの回答を参照してください。
回避策として、DBのCLOBではなくBLOBに格納し、代わりに使用することもできますPreparedStatement#setBinaryStream()
。バイナリデータとして保存されているかどうかは関係ありません。とにかく、このような大きなBase64データをインデックス作成または検索できるようにする必要はありません。
更新:これはオプションではなく、Apache Commons Codecの担当者に、 CODEC-101Base64InputStream
として再調査したバグの修正に時間がかかる可能性があるため、別のサードパーティのBase64APIの使用を検討してください。私はここでそれを見つけました(パブリックドメインなので、あなたはそれを好きなように使うことができ、あなた自身のパッケージに入れることさえできます)、私はここでそれをテストしました、そしてそれはうまくいきます。
InputStream base64 = new Base64.InputStream(input, Base64.ENCODE);
アップデート2:コモンズコーデックの担当者がすぐに修正しました。
Index: src/java/org/apache/commons/codec/binary/Base64InputStream.java
===================================================================
--- src/java/org/apache/commons/codec/binary/Base64InputStream.java (revision 950817)
+++ src/java/org/apache/commons/codec/binary/Base64InputStream.java (working copy)
@@ -145,21 +145,41 @@
} else if (len == 0) {
return 0;
} else {
- if (!base64.hasData()) {
- byte[] buf = new byte[doEncode ? 4096 : 8192];
- int c = in.read(buf);
- // A little optimization to avoid System.arraycopy()
- // when possible.
- if (c > 0 && b.length == len) {
- base64.setInitialBuffer(b, offset, len);
+ int readLen = 0;
+ /*
+ Rationale for while-loop on (readLen == 0):
+ -----
+ Base64.readResults() usually returns > 0 or EOF (-1). In the
+ rare case where it returns 0, we just keep trying.
+
+ This is essentially an undocumented contract for InputStream
+ implementors that want their code to work properly with
+ java.io.InputStreamReader, since the latter hates it when
+ InputStream.read(byte[]) returns a zero. Unfortunately our
+ readResults() call must return 0 if a large amount of the data
+ being decoded was non-base64, so this while-loop enables proper
+ interop with InputStreamReader for that scenario.
+ -----
+ This is a fix for CODEC-101
+ */
+ while (readLen == 0) {
+ if (!base64.hasData()) {
+ byte[] buf = new byte[doEncode ? 4096 : 8192];
+ int c = in.read(buf);
+ // A little optimization to avoid System.arraycopy()
+ // when possible.
+ if (c > 0 && b.length == len) {
+ base64.setInitialBuffer(b, offset, len);
+ }
+ if (doEncode) {
+ base64.encode(buf, 0, c);
+ } else {
+ base64.decode(buf, 0, c);
+ }
}
- if (doEncode) {
- base64.encode(buf, 0, c);
- } else {
- base64.decode(buf, 0, c);
- }
+ readLen = base64.readResults(b, offset, len);
}
- return base64.readResults(b, offset, len);
+ return readLen;
}
}
ここで試してみましたが、問題なく動作します。