出内存文件编码为Base64时 [英] Out of memory when encoding file to base64
问题描述
来自Apache公地使用Base64
Using Base64 from Apache commons
public byte[] encode(File file) throws FileNotFoundException, IOException {
byte[] encoded;
try (FileInputStream fin = new FileInputStream(file)) {
byte fileContent[] = new byte[(int) file.length()];
fin.read(fileContent);
encoded = Base64.encodeBase64(fileContent);
}
return encoded;
}
Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space
at org.apache.commons.codec.binary.BaseNCodec.encode(BaseNCodec.java:342)
at org.apache.commons.codec.binary.Base64.encodeBase64(Base64.java:657)
at org.apache.commons.codec.binary.Base64.encodeBase64(Base64.java:622)
at org.apache.commons.codec.binary.Base64.encodeBase64(Base64.java:604)
我在做小的应用程序的移动设备。
I'm making small app for mobile device.
推荐答案
您不能将整个文件只加载到内存中,喜欢这里:
You cannot just load the whole file into memory, like here:
byte fileContent[] = new byte[(int) file.length()];
fin.read(fileContent);
相反,通过加载块和连接$ C $文件块c将其零件。 Base64是一个简单的编码,就足以在一段时间(编码后,这将产生4个字节)来加载3个字节和连接code他们。出于性能方面的考虑3个字节装载的倍数,例如3000字节 - 应该就好了。还要考虑缓冲输入文件。
Instead load the file chunk by chunk and encode it in parts. Base64 is a simple encoding, it is enough to load 3 bytes and encode them at a time (this will produce 4 bytes after encoding). For performance reasons consider loading multiples of 3 bytes, e.g. 3000 bytes - should be just fine. Also consider buffering input file.
一个例子:
byte fileContent[] = new byte[3000];
try (FileInputStream fin = new FileInputStream(file)) {
while(fin.read(fileContent) >= 0) {
Base64.encodeBase64(fileContent);
}
}
请注意,你不能简单地追加 Base64.en $结果C $ cBase64()
到连接codeD
bbyte阵列。其实,这是不加载的文件,但它编码为Base64导致内存外的问题。这是理解的,因为Base64编码的版本是更大的(并且已经有占大量内存的文件)。
Note that you cannot simply append results of Base64.encodeBase64()
to encoded
bbyte array. Actually, it is not loading the file but encoding it to Base64 causing the out-of-memory problem. This is understandable because Base64 version is bigger (and you already have a file occupying a lot of memory).
考虑更改方法:
public void encode(File file, OutputStream base64OutputStream)
和直接发送的Base64恩codeD数据传输到 base64OutputStream
而不是返回了。
and sending Base64-encoded data directly to the base64OutputStream
rather than returning it.
更新:感谢的 @StephenC 的我开发容易得多版本:
UPDATE: Thanks to @StephenC I developed much easier version:
public void encode(File file, OutputStream base64OutputStream) {
InputStream is = new FileInputStream(file);
OutputStream out = new Base64OutputStream(base64OutputStream)
IOUtils.copy(is, out);
is.close();
out.close();
}
它使用<一个href=\"http://commons.apache.org/$c$cc/api-release/org/apache/commons/$c$cc/binary/Base64OutputStream.html\"><$c$c>Base64OutputStream$c$c>该输入转换为Base64的上即时和<一个href=\"http://commons.apache.org/io/apidocs/org/apache/commons/io/IOUtils.html\"><$c$c>IOUtils$c$c>类从 Apache的百科全书IO 。
注意:您必须关闭的FileInputStream
和 Base64OutputStream
明确打印 =
如果需要的话,但缓冲由 IOUtils.copy()
。
Note: you must close the FileInputStream
and Base64OutputStream
explicitly to print =
if required but buffering is handled by IOUtils.copy()
.
这篇关于出内存文件编码为Base64时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!