如何在没有OutOfMemory错误的情况下从FileInputStream获取字节数组

时间:2013-04-05 04:21:28

标签: java android

我有一个拥有200MB数据的FileInputStream。我必须从输入流中检索字节。

我正在使用下面的代码将InputStream转换为字节数组。

private byte[] convertStreamToByteArray(InputStream inputStream) {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    try {
        int i;
        while ((i = inputStream.read()) > 0) {
            bos.write(i);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return bos.toByteArray();
}

在将如此大的数据转换为字节数组时,我得到了OutOfMemory异常。

请告诉我将InputStream转换为字节数组的任何可能解决方案。

5 个答案:

答案 0 :(得分:9)

为什么要将200MB文件保存在内存中?你打算用字节数组做什么?

如果要将其写入OutputStream,首先准备好OutputStream,然后一次读取一个块的InputStream,然后将块写入OutputStream。你永远不会在内存中存储超过块。

例如:

     public static void pipe(InputStream is, OutputStream os) throws IOException {

        int read = -1;
        byte[] buf = new byte[1024];

        try {
            while( (read = is.read(buf)) != -1) {
                os.write(buf, 0, read);
            }
        }
        finally {
            is.close();
            os.close();
        }
    }

此代码将采用两个流并将其中一个传输到另一个。

答案 1 :(得分:2)

Android应用程序的堆内存有限,依赖于设备。目前大多数新设备有64个,但可能或多或少取决于制造商。我见过设备带有128 MB堆内存。

那究竟是什么意思?

它只是意味着无论可用的物理内存如何,都不允许应用程序增长超过分配的堆大小。

从Android API级别11开始,您可以使用清单标记android:largeHeap="true"来请求额外的内存,这将是您的堆大小的两倍。这只是意味着如果你的设备有64个,你将获得128个,如果是128个,你将获得256个。但这对于较低的API版本不起作用。

我不确定您的要求是什么,但如果您计划通过HTTP发送,则读取文件发送数据并再次阅读。您也可以对文件IO执行相同的过程。只是为了确保不使用更多可用堆大小的内存。只是要格外小心,确保为应用程序执行留出一些空间。

答案 2 :(得分:1)

你的问题不是关于如何将InputStream转换为字节数组,而是数组要大到适合内存。你没有太多选择,只能找到一种方法来处理较小块中InputStream的字节。

答案 3 :(得分:0)

您可能需要大量增加堆大小。尝试使用-Xms384m -Xmx384m标志运行Java虚拟机(指定起始和最大堆大小为384兆字节,除非我错了)。有关可用选项的旧版本,请参阅this:根据特定的虚拟机和平台,您可能需要进行一些挖掘,但-Xms和-Xmx可以帮助您解决这个问题。

现在,您可能真的不应该将其读入字节数组,但如果这是您的应用程序,那么......

答案 4 :(得分:-2)

试试这段代码

private byte[] convertStreamToByteArray(InputStream inputStream) {
ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream();
                    int readByte = 0;
        byte[] buffer = new byte[2024];

                    while(true)
                    {
                        readByte = inputStream.read(buffer);
                        if(readByte == -1)
                        {
                            break;
                        }
                        byteOutStream.write(buffer);
                    }
                    inputStream.close();
                    byteOutStream.flush();
                    byteOutStream.close();
                    byte[] byteArray= byteOutStream.toByteArray();
                    return byteArray;
}

尝试从InputStream读取数据块。