使用 input/output 流复制 android 中的文件:好的和坏的方法
copying files in android with input/output stream: the good and the bad way
我已经制作了这两个例程来使用输入流和输出流复制文件。
它们完全相同,但是第二个上升 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);
}
}
有谁知道为什么 while 有效而 for 无效?我错过了什么?
在调用 is.read()
之前检查 For 循环停止条件。当您尝试读取字节、获得 -1 值的结果并尝试继续执行循环代码时,这允许出现这种情况。 While 在 is.read()
returns -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);
}
问题出在你的 for 循环检查第一个 运行 通过后的条件。基本上,当它在最后一个循环中读取正常但在下一个循环中 is.read
调用 returns -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 循环。
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) {
}
}
}
我已经制作了这两个例程来使用输入流和输出流复制文件。 它们完全相同,但是第二个上升 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);
}
}
有谁知道为什么 while 有效而 for 无效?我错过了什么?
在调用 is.read()
之前检查 For 循环停止条件。当您尝试读取字节、获得 -1 值的结果并尝试继续执行循环代码时,这允许出现这种情况。 While 在 is.read()
returns -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);
}
问题出在你的 for 循环检查第一个 运行 通过后的条件。基本上,当它在最后一个循环中读取正常但在下一个循环中 is.read
调用 returns -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 循环。
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) {
}
}
}