用输入/输出流复制android中的文件:好的和坏的方式

时间:2015-01-29 21:07:56

标签: java android inputstream outputstream

我已经使用inputstream和outpustream复制文件这两个例程。 它们是完全相同的,但第二个引发ArrayIndexOutOfBoundsException,而第一个工作完美无缺,我不知道为什么:

    public void CopyStream(long size, InputStream is, OutputStream os) {
        final int buffer_size = 4096;
        byte[] bytes = new byte[buffer_size];
        try {
            int count,prog=0;
            while ((count = is.read(bytes)) != -1) {
                os.write(bytes, 0, count); //write buffer
                prog = prog + count;
                publishProgress(((long) prog) * 100 / size);
            }
            os.flush();
            is.close();
            os.close();
        } catch (Exception ex) {
            Log.e(TAG,"CS "+ex);
        }
    }

你可能会猜到例程是在AsyncTask中调用的,因此是publishProgresss

    public void CopyStream(long size, InputStream is, OutputStream os) {
        final int buffer_size = 4096;
        try {
            byte[] bytes = new byte[buffer_size];
            for (int count=0,prog=0;count!=-1;) {
                count = is.read(bytes);
                os.write(bytes, 0, count);
                prog=prog+count;
                publishProgress(((long) prog)*100/size);
            }
            os.flush();
            is.close();
            os.close();
        } catch (Exception ex) {
            Log.e(TAG,"CS "+ex);
        }
    }

有谁知道为什么会有效,但对于没有?我错过了什么?

3 个答案:

答案 0 :(得分:2)

问题在于你的for循环在第一次运行后检查条件。基本上,当它在最后一个循环中读取正常但在下一个循环中is.read调用返回-1时发生错误。然后你尝试调用os.write(bytes,0,-1); -1是无效索引。解决方案是:

public void CopyStream(long size, InputStream is, OutputStream os) {
        final int buffer_size = 4096;
        try {
            byte[] bytes = new byte[buffer_size];
            for (int count=0,prog=0;count!=-1;) {
                count = is.read(bytes);
                if(count != -1) {
                  os.write(bytes, 0, count);
                  prog=prog+count;
                  publishProgress(((long) prog)*100/size);
                }
            }
            os.flush();
            is.close();
            os.close();
        } catch (Exception ex) {
            Log.e(TAG,"CS "+ex);
        }
    }

但它作为while循环更具可读性,所以我会坚持下去。 For循环应该在你知道循环次数时使用,或者在循环遍历集合中每个项目的每个循环中使用。

答案 1 :(得分:0)

在调用is.read()之前检查循环停止条件。当你尝试读取字节,得到-1值的结果并尝试继续执行循环代码时,这允许这种情况。在is.read()返回-1后立即停止

请尝试以下操作:

int count = is.read(bytes);
for (prog=0;count!=-1;) {
     os.write(bytes, 0, count);
     prog=prog+count;
     publishProgress(((long) prog)*100/size);
     count = is.read(bytes);
}

答案 2 :(得分:0)

private static final int BASE_BUFFER_SIZE = 4096;

public static void copyFile(InputStream inputStream, OutputStream outputStream)
        throws IOException {
    byte[] bytes = new byte[BASE_BUFFER_SIZE];
    int count;

    while ((count = inputStream.read(bytes)) != -1){
        outputStream.write(bytes, 0, count);
    }

    close(inputStream);
    close(outputStream);
}

public static void close(@Nullable OutputStream stream) {
    if (stream != null) {
        try {
            stream.flush();
        } catch (IOException ignored) {
        }
        try {
            stream.close();
        } catch (IOException ignored) {
        }
    }
}

public static void close(@Nullable InputStream stream) {
    if (stream != null) {
        try {
            stream.close();
        } catch (IOException ignored) {
        }
    }
}