IOUtils.toByteArray()导致OutOfMemoryError

3

我正在尝试压缩一个大小超过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();
        }           
    }

每次我遇到OutOfMemoryError错误。


1
那么你的问题是什么?我认为在移动平台上将100 MB加载到内存中并因此导致OOM是相当正常的。不要这样做。 - Axel
2个回答

4

您应该逐步复制数据,这样就不会耗尽内存。

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在执行其工作时也会使用大约相同的缓冲区)


好的,我得到了一个资源规范不允许在低于1.7版本的源码级别上使用,因为我使用的是Java 1.6。如果我切换到Java 1.7,则会出现Android需要编译器符合级别5.0或6.0的错误。而实际找到的是'1.7'版本。 - user3056448

0

你可以使用:

IOUtils.copy(inputStream, outputStream);

这个程序会自行处理字节缓冲区。你不需要显式地创建一个byte[],因为如果大小很大,你可以使用以下方法将大字节数组加载到内存中:

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接