Копирование файлов в android с потоком ввода/вывода: хороший и плохой способ
Я сделал эти две процедуры для копирования файлов с помощью 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);
}
}
Кто-нибудь знает, почему работает, но нет? что мне не хватает?
Ответы
Ответ 1
Проблема заключается в том, что ваш цикл цикла проверяет состояние после первого прогона. В основном ошибка возникает, когда она отлично считывает последний цикл, но в следующем цикле вызов is.read
возвращает -1. Впоследствии вы пытаетесь вызвать os.write(байты, 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, поэтому я буду придерживаться этого. Для циклов следует использовать либо когда вы знаете количество циклов или циклов для каждого, где вы прокручиваете каждый отдельный элемент коллекции.
Ответ 2
Условие остановки цикла проверяется перед вызовом 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);
}
Ответ 3
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) {
}
}
}