【问题标题】:IOUtils.toByteArray() OutOfMemoryErrorIOUtils.toByteArray() OutOfMemoryError
【发布时间】:2014-04-24 10:08:25
【问题描述】:

我尝试压缩大小超过 100Mb 的大型视频文件。

public static void compress(File input, File output) throws    IOException {
        InputStream fis = new FileInputStream(input);
        byte[] bFile = IOUtils.toByteArray(fis);
        FileOutputStream fos = new FileOutputStream(output);
        GZIPOutputStream gzipStream = new GZIPOutputStream(fos);
        try {
            gzipStream.write(bFile);
            // IOUtils.copy(fis, gzipStream);
        } finally {
            gzipStream.close();
            fis.close();
            fos.close();
        }           
    }

每次我遇到内存不足错误。

【问题讨论】:

  • 那么你的问题是什么?我认为在移动平台上将 100 MB 加载到内存中时出现 OOM 是很正常的。不要这样做。

标签: java android garbage-collection out-of-memory


【解决方案1】:

您应该逐步复制数据,并且不会耗尽内存。

public static void compress(File input, File output) throws IOException {
    try(InputStream in = new FileInputStream(input);
        OutputStream out = new GZIPOutputStream(new FileOutputStream(output))) {
        byte[] bytes = new byte[4096];
        for(int len; (len = in.read(bytes)) > 0; )
            out.write(bytes, 0, len);
    }           
}

这将一次使用大约 4 KB 作为缓冲区,无论文件大小如何。 (我怀疑 GZIP 使用大致相同的方式来完成它的工作)

【讨论】:

  • 好的,因为我使用 java 1.6,所以对于低于 1.7 的源级别,我在此处不允许使用资源规范。如果我切换到 java 1.7,我得到这个 Android 需要编译器合规级别 5.0 或 6.0。改为找到“1.7”
【解决方案2】:

你可以使用:

IOUtils.copy(inputStream, outputStream);

它将自己处理字节缓冲区。您不需要显式创建一个 byte[],因为在大尺寸的情况下,您正在使用以下方法在内存中加载大尺寸字节数组:

IOUtils.toByteArray(fis); // 这会将整个字节数组加载到内存中。

【讨论】:

    猜你喜欢
    • 2016-03-05
    • 2012-11-12
    • 1970-01-01
    • 1970-01-01
    • 2011-05-16
    • 2011-01-18
    • 2013-06-21
    • 2013-11-18
    • 1970-01-01
    相关资源
    最近更新 更多