Программа на Android устройстве пакует файлы из /files/ в архив. Необходимо извлекать архив с помощью adb (другая программа на ПК должна будет запустить bat файл с командой для adb). Если извлечь архив с помощью файлового менеджера Android Studio, то с архивом всё будет в порядке, если это делать командой для adb:
adb.exe -e shell "run-as com.example.ivan.fgc cat /data/data/com.example.ivan.fgc/files/archive.zip" > archive.zip
то один из файлов архива всегда повреждён ("ошибка контрольной суммы" или "неожиданный конец архива"). Подскажите, пожалуйста, возможные причины такого поведения или посоветуйте пути обхода данной проблемы.
Код создания архива:
/**
* Упаковывает все файлы директории files и дополняет ими архив archive.zip
*
* @param context Контекст
* @throws IOException Исключение записи/чтения
*/
@SuppressWarnings("ResultOfMethodCallIgnored")
public void packIntoArchive(Context context) throws IOException {
ArrayList<File> files = getFiles(new File(context.getFilesDir().getPath()));
if (!files.isEmpty()) {
FileOutputStream fos = new FileOutputStream(context.getFilesDir().getPath() + "/archive.zip", true);
ZipOutputStream zipOut = new ZipOutputStream(fos);
for (File file : files) {
FileInputStream fis = new FileInputStream(file);
ZipEntry zipEntry = new ZipEntry(file.getPath().substring(context.getFilesDir().getPath().length() + 1));
zipOut.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while ((length = fis.read(bytes)) > 0) {
zipOut.write(bytes, 0, length);
}
zipOut.closeEntry();
fis.close();
file.delete();
}
zipOut.close();
fos.close();
removeFilesNDirs(new File(context.getFilesDir().getPath()));
}
}
/**
* Удалить всё кроме архивов из папки
*
* @param dir Директория
*/
@SuppressWarnings("ResultOfMethodCallIgnored")
private void removeFilesNDirs(File dir) {
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
removeFilesNDirs(file);
}
if (!file.getName().contains(".zip")) {
file.delete();
}
}
}
/**
* Получить все файлы из директории (за исключением архивов)
*
* @param dir Папка
* @return Массив файлов
*/
private ArrayList<File> getFiles(File dir) {
ArrayList<File> filesNDirs = new ArrayList<>(Arrays.asList(dir.listFiles()));
ArrayList<File> files = new ArrayList<>();
Iterator<File> iterator = filesNDirs.iterator();
while (iterator.hasNext()) {
File file = iterator.next();
if (file.isDirectory()) {
files.addAll(getFiles(file));
iterator.remove();
} else {
if (!file.getName().contains(".zip")) {
files.add(file);
}
}
}
return files;
}
UPD: Открыл оба архива, внутри показывает, что файлы обоих архивов одинаковы по размеру, как и суммарный их размер, а в их поле CRC32 одинаковые значения. Однако повреждённый архив всегда больше на некоторое количество байт (отличия были на 56, 42, 14, 12). Поле Свойства->Архив у "здорового" в порядке, у второго везде "0" или "неизвестно"
UPD: Частично обошли проблему. На реальном планшете сработало так:
adb.exe -d shell "run-as com.example.ivan.fgc cp /data/data/com.example.ivan.fgc/files/archive.zip" /sdcard/archive.zip
adb.exe pull /sdcard/archive.zip
Виртуальное устройство на команду cp отзывается "permission denied"
Сборка персонального компьютера от Artline: умный выбор для современных пользователей