使用base64编码器和InputStreamReader的问题
我的数据库中有一些 CLOB 列,我需要将 Base64 编码的二进制文件放入其中。 这些文件可能很大,所以我需要流式传输它们,我无法一次读取整个文件。
我正在使用 org.apache.commons.codec.binary.Base64InputStream 进行编码,但遇到了问题。我的代码本质上是这样
FileInputStream fis = new FileInputStream(file);
Base64InputStream b64is = new Base64InputStream(fis, true, -1, null);
BufferedReader reader = new BufferedReader(new InputStreamReader(b64is));
preparedStatement.setCharacterStream(1, reader);
当我运行上面的代码时,我在执行更新期间得到其中之一 java.io.IOException:底层输入流返回零字节
,它被抛出到InputStreamReader代码深处。
为什么这不起作用?在我看来,reader
会尝试从 Base 64 流中读取,而该流会从文件流中读取,一切都应该很顺利。
I have some CLOB columns in a database that I need to put Base64 encoded binary files in.
These files can be large, so I need to stream them, I can't read the whole thing in at once.
I'm using org.apache.commons.codec.binary.Base64InputStream
to do the encoding, and I'm running into a problem. My code is essentially this
FileInputStream fis = new FileInputStream(file);
Base64InputStream b64is = new Base64InputStream(fis, true, -1, null);
BufferedReader reader = new BufferedReader(new InputStreamReader(b64is));
preparedStatement.setCharacterStream(1, reader);
When I run the above code, I get one of these during the execution of the updatejava.io.IOException: Underlying input stream returned zero bytes
, it is thrown deep in the InputStreamReader code.
Why would this not work? It seems to me like the reader
would attempt to read from the base 64 stream, which would read from the file stream, and everything should be happy.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这似乎是
Base64InputStream
中的一个错误。你调用它是正确的。您应该将此报告给 Apache commons 编解码器项目。
简单测试用例:
InputStream
的read(byte[])
调用不允许返回 0。它确实在任何长度为 3 字节倍数的文件上返回 0 。This appears to be a bug in
Base64InputStream
. You're calling it correctly.You should report this to the Apache commons codec project.
Simple test case:
the
read(byte[])
call ofInputStream
is not allowed to return 0. It does return 0 on any file which is a multiple of 3 bytes long.有趣的是,我在这里做了一些测试,当您使用
InputStreamReader
读取Base64InputStream
时,无论流的来源如何,它确实会抛出该异常,但当您读取时它可以完美地工作它作为二进制流。正如 Trashgod 提到的,Base64 编码是有框架的。实际上,InputStreamReader
应该再次调用Base64InputStream
上的flush()
,以查看它是否不再返回任何数据。除了实现您自己的之外,我没有看到其他方法可以解决此问题。 这实际上是一个错误,请参阅 Keith 的回答。Base64InputStreamReader
或Base64Reader
作为一种解决方法,您也可以将其存储在数据库中的 BLOB 而不是 CLOB 中,并使用
PreparedStatement#setBinaryStream()
反而。是否存储为二进制数据并不重要。无论如何,您都不希望有如此大的 Base64 数据可索引或可搜索。更新:因为这不是一个选项,并且让 Apache Commons Codec 人员修复
Base64InputStream
错误,我将其报告为 CODEC-101 可能需要一些时间,您可以考虑使用其他第 3 方 Base64 API。我在这里找到了一个(公共领域,所以你可以用它做任何事情你想要的,甚至放在你自己的包中),我在这里测试过它,它工作得很好。更新 2:commons 编解码器人员已修复了很快。
我在这里尝试了一下,效果很好。
Interesting, I did some tests here and it indeed throws that exception when you read the
Base64InputStream
using anInputStreamReader
, regardless the source of the stream, but it works flawlessly when you read it as binary stream. As Trashgod mentioned, Base64 encoding is framed. TheInputStreamReader
should in fact have invokedflush()
on theBase64InputStream
once more to see if it doesn't return any more data.I don't see other ways to fix this than implementing your own. This is actually a bug, see Keith's answer.Base64InputStreamReader
orBase64Reader
As a workaround you can also just store it in a BLOB instead of a CLOB in the DB and use
PreparedStatement#setBinaryStream()
instead. It doesn't matter if it's stored as binary data or not. You don't want to have such large Base64 data to be indexable or searchable anyway.Update: since that's not an option and having the Apache Commons Codec guys to fix the
Base64InputStream
bug which I repored as CODEC-101 might take some time, you may consider to use another 3rd party Base64 API. I've found one here (public domain, so you can do whatever with it you want, even place in your own package), I've tested it here and it works fine.Update 2: the commons codec guy has fixed it pretty soon.
I tried it here and it works fine.
“为了获得最高效率,请考虑包装
InputStreamReader
内BufferedReader
例如:“附录:作为
Base64
已填充为 4 个字符的倍数,请验证源代码是否未被截断。可能需要
flush()
。"For top efficiency, consider wrapping an
InputStreamReader
within aBufferedReader
. For example:"Addendum: As
Base64
is padded to a multiple of 4 characters, verify that the source isn't truncated. Aflush()
may be required.