简体   繁体   English

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

[英]How to get a byte array from FileInputStream without OutOfMemory error

I have a FileInputStream which has 200MB of data. 我有一个拥有200MB数据的FileInputStream。 I have to retrieve the bytes from the input stream. 我必须从输入流中检索字节。

I'm using the below code to convert InputStream into byte array. 我正在使用下面的代码将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();
}

I'm getting OutOfMemory exception while coverting such a large data to a byte array. 在将如此大的数据转换为字节数组时,我得到了OutOfMemory异常。

Kindly let me know any possible solutions to convert InputStream to byte array. 请告诉我将InputStream转换为字节数组的任何可能的解决方案。

Why do you want to hold the 200MB file in memory? 为什么要将200MB文件保存在内存中? What are you going to to with the byte array? 你打算用字节数组做什么?

If you are going to write it to an OutputStream, get the OutputStream ready first, then read the InputStream a chunk at a time, writing the chunk to the OutputStream as you go. 如果要将其写入OutputStream,首先准备好OutputStream,然后一次读取一个块的InputStream,然后将块写入OutputStream。 You'll never store more than the chunk in memory. 你永远不会在内存中存储超过块。

eg: 例如:

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

This code will take two streams and pipe one to the other. 此代码将采用两个流并将一个管道连接到另一个。

Android application has limited Heap Memory and which depend on devices. Android应用程序的堆内存有限,依赖于设备。 Currently most of the new devices has 64 but it could be more or less depend on Manufacturer. 目前大多数新设备有64个,但可能或多或少取决于制造商。 I have seen device come come with 128 MB heap Memory. 我见过设备带有128 MB堆内存。

So what this really mean? 那真的是什么意思呢?

Its simply means that regardless of available physical memory your application is not allowed to grow more then allocated heap size. 它只是意味着无论可用的物理内存如何,都不允许应用程序增长超过分配的堆大小。

From Android API level 11 you can request for additional memory by using manifest tag android:largeHeap="true" which will be double your heap size. 从Android API级别11开始,您可以使用清单标记android:largeHeap="true"来请求额外的内存,这将是您的堆大小的两倍。 That simply means if your devices has 64 you will get 128 and in case of 128 you will get 256. But this will not work for lower API version. 这只是意味着如果你的设备有64个,你将获得128个,如果是128个,你将获得256个。但这对于较低的API版本不起作用。

I am not exactly sure what is your requirement, but if you planning to send over HTTP then read file send data and read again. 我不确定您的要求是什么,但如果您计划通过HTTP发送,则读取文件发送数据并再次读取。 You can follow the same procedure for file IO also. 您也可以对文件IO执行相同的过程。 Just to make sure not to use memory more then available heap size. 只是为了确保不使用更多可用堆大小的内存。 Just to be extra cautious make sure you leave some room for application execution. 只是要格外小心,确保为应用程序执行留出一些空间。

Your problem is not about how to convert InputStream to byte array but that the array is to big to fit in memory. 您的问题不是关于如何将InputStream转换为字节数组,而是该数组要大到适合内存。 You don't have much choice but to find a way to process bytes from InputStream in smaller blocks. 除了找到一种在较小的块中处理来自InputStream的字节的方法之外,您没有太多选择。

You'll probably need to massively increase the heap size. 您可能需要大量增加堆大小。 Try running your Java virtual machine with the -Xms384m -Xmx384m flag (which specifies a starting and maximum heap size of 384 megabytes, unless I'm wrong). 尝试使用-Xms384m -Xmx384m标志运行Java虚拟机(指定起始和最大堆大小为384兆字节,除非我错了)。 See this for an old version of the available options: depending on the specific virtual machine and platform you may need to do some digging around, but -Xms and -Xmx should get you over that hump. 请参阅版本以获取旧版本的可用选项:根据特定的虚拟机和平台,您可能需要进行一些挖掘,但-Xms和-Xmx应该可以帮助您解决这个问题。

Now, you probably really SHOULDN'T read it into a byte array, but if that's your application, then... 现在,您可能真的不应该将其读入字节数组,但如果这是您的应用程序,那么......

try this code 试试这段代码

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

try to read chunk of data from InputStream . 尝试从InputStream中读取数据块。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM