使用来自 Apache commons 的 Base64
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)
我正在为移动设备制作小应用。
最佳答案
你不能像这里一样将整个文件加载到内存中:
byte fileContent[] = new byte[(int) file.length()];
fin.read(fileContent);
而是逐 block 加载文件并分段编码。 Base64是一种简单的编码,一次加载3个字节并编码就足够了(编码后会产生4个字节)。出于性能原因考虑加载 3 字节的倍数,例如3000 字节 - 应该没问题。还要考虑缓冲输入文件。
一个例子:
byte fileContent[] = new byte[3000];
try (FileInputStream fin = new FileInputStream(file)) {
while(fin.read(fileContent) >= 0) {
Base64.encodeBase64(fileContent);
}
}
请注意,您不能简单地将 Base64.encodeBase64()
的结果附加到 encoded
bbyte 数组。实际上,它不是加载文件而是将其编码为 Base64 导致内存不足问题。这是可以理解的,因为 Base64 版本更大(并且您已经有一个占用大量内存的文件)。
考虑将您的方法更改为:
public void encode(File file, OutputStream base64OutputStream)
并将 Base64 编码的数据直接发送到 base64OutputStream
而不是返回它。
更新:感谢@StephenC,我开发了更简单的版本:
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();
}
它使用 Base64OutputStream
将输入翻译成 Base64 on-the-fly 和 IOUtils
来自 Apache Commons IO 的类(class).
注意:如果需要,您必须显式关闭 FileInputStream
和 Base64OutputStream
以打印 =
但缓冲由 IOUtils.copy 处理()
。
关于java - 将文件编码为 base64 时内存不足,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9579874/