Android: распаковка файлов приводит к ошибкам данных или ошибкам CRC

Я работаю над проектом, который загружает zip-файл и распаковывает его локально. Проблема, с которой я сталкиваюсь, заключается в том, что процесс распаковки работает как 5% времени.

Для меня это тайна, потому что иногда она работает, но большую часть времени она выдает данные или ошибки crc. Он даже переключится между erros, даже если zip-файл не изменился.

Я пробовал zip-файлы, созданные несколькими инструментами, задаваясь вопросом, был ли формат неправильным. Но безрезультатно. Даже ZIP-файлы, созданные в терминале, не работают.

Вот мой расстегивающий код:

try { String _location = model.getLocalPath(); FileInputStream fin = new FileInputStream(localFile); ZipInputStream zin = new ZipInputStream(fin); ZipEntry ze = null; byte[] buffer = new byte[1024]; while((ze = zin.getNextEntry()) != null) { if(_cancel) break; System.out.println("unzipping " + ze.getName()); if(ze.isDirectory()) { File f = new File(_location + ze.getName()); f.mkdirs(); } else { FileOutputStream fout = new FileOutputStream(_location + ze.getName()); for(int c = zin.read(buffer); c > 0; c = zin.read(buffer)) { fout.write(buffer,0,c); } zin.closeEntry(); fout.close(); } } zin.close(); if(_cancel) { handler.post(dispatchCancel); return; } } catch(Exception e) { System.out.println("UNZIP ERROR!"); System.out.println(e.getMessage()); System.out.println(e.toString()); e.printStackTrace(); } 

И вот как я обычно создаю zip-файл.

 $>zip -r myzip.zip myzip/ 

Вот два выхода ошибки:

 java.util.zip.ZipException: CRC mismatch at java.util.zip.ZipInputStream.readAndVerifyDataDescriptor(ZipInputStream.java:209) at java.util.zip.ZipInputStream.closeEntry(ZipInputStream.java:173) at com.XX.XX.XXIssueDownloader$7.run(XXIssueDownloader.java:222) at java.lang.Thread.run(Thread.java:1020) java.util.zip.ZipException: data error at java.util.zip.ZipInputStream.read(ZipInputStream.java:336) at java.io.FilterInputStream.read(FilterInputStream.java:133) at com.XX.XX.XXIssueDownloader$7.run(XXIssueDownloader.java:219) at java.lang.Thread.run(Thread.java:1020) 

У кого-нибудь есть идея, почему я могу получить эти ошибки? Я никуда не дену с ними.

При загрузке Zip-файлов важны две вещи.

  1. Убедитесь, что вы используете метод запроса, который не содержит заголовок Accept-Encoding :. Если это в запросе, тогда ответ не является zip-файлом, это сжатый zip-файл gzip. Поэтому, если вы пишете это прямо на диске во время загрузки, то это фактически не будет zip-файл. Вы можете использовать что-то подобное для загрузки zip-файла:

     URL url = new URL(remoteFilePath); URLConnection connection = url.openConnection(); InputStream in = new BufferedInputStream(connection.getInputStream()); FileOutputStream f = new FileOutputStream(localFile); //setup buffers and loop through data byte[] buffer = new byte[1024]; long total = 0; long fileLength = connection.getContentLength(); int len1 = 0; while((len1 = in.read(buffer)) != -1) { if(_cancel) break; total += len1; _Progress = (int) (total * 100 / fileLength); f.write(buffer,0,len1); handler.post(updateProgress); } f.close(); in.close(); 
  2. При использовании входных и выходных потоков НЕ используйте метод чтения (буфера) или записи (буфера), вам нужно использовать чтение / запись (буфер, 0, len). В противном случае то, что вы пишете или читаете, может закончиться с данными мусора. Первый (read (buffer)) всегда будет считывать весь буфер, но фактически не может быть полный буфер, например, если последняя итерация цикла считывает только 512 байт. Итак, вот как вы распакуете файл:

     String _location = model.getLocalPath(); FileInputStream fin = new FileInputStream(localFile); ZipInputStream zin = new ZipInputStream(fin); ZipEntry ze = null; while((ze = zin.getNextEntry()) != null) { if(_cancel) break; System.out.println("unzipping " + ze.getName()); System.out.println("to: " + _location + ze.getName()); if(ze.isDirectory()) { File f = new File(_location + ze.getName()); f.mkdirs(); } else { byte[] buffer2 = new byte[1024]; FileOutputStream fout = new FileOutputStream(_location + ze.getName()); for(int c = zin.read(buffer2); c > 0; c = zin.read(buffer2)) { fout.write(buffer2,0,c); } zin.closeEntry(); fout.close(); } } zin.close();