4

我有一个包含 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 转换为字节数组的任何可能的解决方案。

4

5 回答 5

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();
        }
    }

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

于 2013-04-05T10:31:51.607 回答
2

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

那么这到底是什么意思呢?

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

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

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

于 2013-04-05T04:37:42.913 回答
1

您的问题不在于如何将 InputStream 转换为字节数组,而是该数组太大而无法放入内存。您别无选择,只能找到一种方法以较小的块处理来自 InputStream 的字节。

于 2013-04-05T04:37:29.837 回答
0

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

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

于 2013-04-05T04:28:21.463 回答
-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 读取数据块。

于 2013-04-05T05:00:15.757 回答