使用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)
Run Code Online (Sandbox Code Playgroud)
我正在为移动设备制作小应用程序.
Tom*_*icz 31
您不能只将整个文件加载到内存中,如下所示:
byte fileContent[] = new byte[(int) file.length()];
fin.read(fileContent);
Run Code Online (Sandbox Code Playgroud)
而是按块加载文件块并将其编码为部分.Base64是一个简单的编码,它足以加载3个字节并一次编码(这将在编码后产生4个字节).出于性能原因,考虑加载3个字节的倍数,例如3000个字节 - 应该没问题.还要考虑缓冲输入文件.
一个例子:
byte fileContent[] = new byte[3000];
try (FileInputStream fin = new FileInputStream(file)) {
while(fin.read(fileContent) >= 0) {
Base64.encodeBase64(fileContent);
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,您不能简单地将结果附加Base64.encodeBase64()到encodedbbyte数组.实际上,它没有加载文件,而是将其编码为Base64导致内存不足问题.这是可以理解的,因为Base64版本更大(并且您已经拥有占用大量内存的文件).
考虑将您的方法更改为:
public void encode(File file, OutputStream base64OutputStream)
Run Code Online (Sandbox Code Playgroud)
并将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();
}
Run Code Online (Sandbox Code Playgroud)
它采用Base64OutputStream的是输入转换为Base64 的即时和IOUtils类从Apache的百科全书IO.
注意:如果需要,您必须关闭FileInputStream并Base64OutputStream显式打印=,但缓冲由IOUtils.copy().处理.
好吧,不要一次对整个文件执行此操作。
Base64 一次处理 3 个字节,因此您可以批量读取“3 个”字节的文件,对它们进行编码并重复,直到完成文件:
// the base64 encoding - acceptable estimation of encoded size
StringBuilder sb = new StringBuilder(file.length() / 3 * 4);
FileInputStream fin = null;
try {
fin = new FileInputStream("some.file");
// Max size of buffer
int bSize = 3 * 512;
// Buffer
byte[] buf = new byte[bSize];
// Actual size of buffer
int len = 0;
while((len = fin.read(buf)) != -1) {
byte[] encoded = Base64.encodeBase64(buf);
// Although you might want to write the encoded bytes to another
// stream, otherwise you'll run into the same problem again.
sb.append(new String(buf, 0, len));
}
} catch(IOException e) {
if(null != fin) {
fin.close();
}
}
String base64EncodedFile = sb.toString();
Run Code Online (Sandbox Code Playgroud)
文件太大,或者堆太小,或者你有内存泄漏.
如果这只发生在非常大的文件中,请在代码中添加一些内容来检查文件大小并拒绝不合理的大文件.
如果小文件发生这种情况,请在启动JVM时使用-Xmx命令行选项增加堆大小.(如果这是在Web容器或其他框架中,请查看有关如何执行此操作的文档.)
如果文件重复出现,特别是对于小文件,则可能是内存泄漏.
另一点应该是你当前的方法需要在内存中保存两个完整的文件副本.您应该能够减少内存使用量,但通常需要基于流的Base64编码器才能执行此操作.(这取决于您使用的base64编码的风格......)
此页面描述了基于流的Base64编码器/解码器库,并包含一些替代方案的lnks.
| 归档时间: |
|
| 查看次数: |
26712 次 |
| 最近记录: |