一次将文件的一部分作为byte []

时间:2013-09-16 18:40:06

标签: java android file stream bytearray

我试图一次处理10MB字节数组的大文件。 我试图一次获取一个字节数组(不是获取大文件的整个字节数组并拆分字节数组,所有问题都是由于内存造成的)

这是我到目前为止所做的:

private byte[] readFile(File file, int offset) throws IOException
{
    BufferedInputStream inStream = null;
    ByteArrayOutputStream outStream = null;
    byte[] buf = new byte[1048576];
    int read = 0;

    try
    {
        inStream = new BufferedInputStream(new FileInputStream(file));
        outStream = new ByteArrayOutputStream();
        long skipped = inStream.skip(offset);
        read = inStream.read(buf);
        if (read != -1)
        {
            outStream.write(buf, 0, read);
            return outStream.toByteArray();
        }
    }
    finally
    {
        if (inStream != null) {try {inStream.close();} catch (IOException e) {}}
        if (outStream != null) {try {outStream.close();} catch (IOException e) {}}
    }

    return null;

参数offset也将以10MB为增量。

所以我遇到的问题是,即使skipped长变量给我跳过了1048576个字节,我想从调用readFile(file, 1048576)接收的第二个10MB是与前10MB的第一个字节数组相同。因此,它根本没有超过前10MB。

这里的问题是什么?还有另一种实现这个想法的方法吗?

2 个答案:

答案 0 :(得分:1)

重新设计方法。目前你正在复制字节数组,就像它的样式一样:一次从缓冲区到ByteArrayOutoutStream,再从那里再到返回值。所以你需要同时使用其中的三个。更改方法的签名,以便调用者提供字节数组以及偏移量和流,并让它返回计数。换句话说,完全摆脱它,只需从你调用它的地方调用FileInputStream.read(buffer,offset,length)。

答案 1 :(得分:0)

因此,根据用户@EJP,我修改了代码以便有效地工作。我不再复制到ByteArrayOutputStream因为我意识到.toByteArray实际上返回了读取字节数组的副本并且内存效率非常低。我也只打开一次流,因此不需要跳过。

    int fileLength = (int) file.length();
    byte[] buffer = new byte[fileLength < FILE_UPLOAD_CHUNK_SIZE ?
            fileLength : FILE_UPLOAD_CHUNK_SIZE];
    int bytesRead;
    int readTotal = 0;
    BufferedInputStream inStream = null;
    try
    {
        inStream = new BufferedInputStream(new FileInputStream(file));
        do
        {
            bytesRead = inStream.read(buffer, 0, buffer.length);
            if (bytesRead == -1)
            {
                continue;
            }
            byte[] finalBuffer;
            if (buffer.length > bytesRead)
            {
                finalBuffer = Arrays.copyOf(buffer, bytesRead);
            }
            else
            {
                finalBuffer = buffer;
            }
            uploadChunk(
                    finalBuffer,
                    mimeType,
                    uploadPath,
                    fileLength,
                    readTotal,
                    readTotal + bytesRead - 1);
            readTotal += bytesRead;
        } while (bytesRead != -1);
    }
    finally
    {
        if (inStream != null)
        {
            inStream.close();
        }
    }

我对此代码的唯一缺陷是当最后一个块小于10MB时我必须创建字节数组的新副本。应该有一种更有效的方法,但这对我来说现在很好。