java - 将文件编码为 base64 时内存不足

标签 java base64

使用来自 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-flyIOUtils来自 Apache Commons IO 的类(class).

注意:如果需要,您必须显式关闭 FileInputStreamBase64OutputStream 以打印 = 但缓冲由 IOUtils.copy 处理()

关于java - 将文件编码为 base64 时内存不足,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9579874/

相关文章:

java - 使用自定义模式定义的 Spring Ldap 单元测试

java - 在新值(value)出现之前先弄清楚科学按钮

java - 是否可以在验证后将 input.next 作为可变长度参数列表中的参数直接传递给方法? <在java中>

python - 字节消息参数错误

java - 双重运算的错误输出

java - Java 方法分派(dispatch)如何与泛型和抽象类一起工作?

python - 无法解码 base64 编码的图像

linux - 如何在 linux 中解码 base64 编码的行?

php - 将所有图像从 mysql 数据库 blob 提取到目录

java - 比 Base64 更短的编码