No se puede extraer el archivo del archivo ZIP creado en Android (específico de dispositivo / OS)

Estoy creando un archivo en Android usando el código como este:

OutputStream os = new FileOutputStream(zipFile); ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(os)); try { zos.setLevel(8); byte[] buffer = new byte[32768]; for (VFile src : toPack) { ZipEntry entry = new ZipEntry(src.name); zos.putNextEntry(entry); src.pushToStream(zos, buffer); src.close(); zos.closeEntry(); } } finally { zos.close(); } 

Encontré que hay solamente un método de la compresión disponible – DEFLATED (hay solamente la alternativa STORED disponible). Esto significa que el archivo siempre se comprime con un método.

Si ejecuto este código en Android 2.3.4 – puedo descomprimir archivos en Windows usando 7Zip; Si ejecuto esto en Android 3 (o Samsung Galaxy Tab, no estoy seguro de quién lo hace mal) – 7Zip muestra la lista de archivos, pero no puede descomprimir archivo diciendo Unsupported método de compresión . Al mismo tiempo 7Zip muestra Deflate como un método de compresión en el archivo, lo que significa que puede tratarlo correctamente.

¿Alguien tiene este problema?

Gracias.

UDP: Encontró otro tema con un problema similar (puede no ser el mismo aunque).

La respuesta de @ user1269737 es correcta; casi. Pero sólo funciona para archivos de un solo archivo. A continuación se muestra un código que analiza todo el archivo.

 /** * Replace wrong local file header byte * http://sourceforge.net/tracker/?func=detail&aid=3477810&group_id=14481&atid=114481 * Applies to Android API 9-13 * @param zip file * @throws IOException */ private static void fixInvalidZipFile(File zip) throws IOException { RandomAccessFile r = new RandomAccessFile(zip, "rw"); try { long eocd_offset = findEOCDRecord(r); if (eocd_offset > 0) { r.seek(eocd_offset + 16); // offset of first CDE in EOCD long cde_offset = readInt(r); // read offset of first Central Directory Entry long lfh_offset = 0; long fskip, dskip; while (true) { r.seek(cde_offset); if (readInt(r) != CDE_SIGNATURE) // got off sync! return; r.seek(cde_offset + 20); // compressed file size offset fskip = readInt(r); // fix the header // r.seek(lfh_offset + 7); short localFlagsHi = r.readByte(); // hi-order byte of local header flags (general purpose) r.seek(cde_offset + 9); short realFlagsHi = r.readByte(); // hi-order byte of central directory flags (general purpose) if (localFlagsHi != realFlagsHi) { // in latest versions this bug is fixed, so we're checking is bug exists. r.seek(lfh_offset + 7); r.write(realFlagsHi); } // calculate offset of next Central Directory Entry // r.seek(cde_offset + 28); // offset of variable CDE parts length in CDE dskip = 46; // length of fixed CDE part dskip += readShort(r); // file name dskip += readShort(r); // extra field dskip += readShort(r); // file comment cde_offset += dskip; if (cde_offset >= eocd_offset) // finished! break; // calculate offset of next Local File Header // r.seek(lfh_offset + 26); // offset of variable LFH parts length in LFH fskip += readShort(r); // file name fskip += readShort(r); // extra field fskip += 30; // length of fixed LFH part fskip += 16; // length of Data Descriptor (written after file data) lfh_offset += fskip; } } } finally { r.close(); } } //http://www.pkware.com/documents/casestudies/APPNOTE.TXT private static final int LFH_SIGNATURE = 0x04034b50; private static final int DD_SIGNATURE = 0x08074b50; private static final int CDE_SIGNATURE = 0x02014b50; private static final int EOCD_SIGNATURE = 0x06054b50; /** Find an offset of End Of Central Directory record in file */ private static long findEOCDRecord(RandomAccessFile f) throws IOException { long result = f.length() - 22; // 22 is minimal EOCD record length while (result > 0) { f.seek(result); if (readInt(f) == EOCD_SIGNATURE) return result; result--; } return -1; } /** Read a 4-byte integer from file converting endianness. */ private static int readInt(RandomAccessFile f) throws IOException { int result = 0; result |= f.read(); result |= (f.read() << 8); result |= (f.read() << 16); result |= (f.read() << 24); return result; } /** Read a 2-byte integer from file converting endianness. */ private static short readShort(RandomAccessFile f) throws IOException { short result = 0; result |= f.read(); result |= (f.read() << 8); return result; } 

Necesidad de ser actualizado. Se corrige single-file-zip. Debe buscar la siguiente secuencia en el archivo zip {0, 0x08, 0x08, 0x08, 0} y reemplazarlo por {0, 0x08, 0x00, 0x08, 0}

 /** * Replace wrong byte http://sourceforge.net/tracker/?func=detail&aid=3477810&group_id=14481&atid=114481 * @param zip file * @throws IOException */ private static void replaceWrongZipByte(File zip) throws IOException { RandomAccessFile r = new RandomAccessFile(zip, "rw"); int flag = Integer.parseInt("00001000", 2); //wrong byte r.seek(7); int realFlags = r.read(); if( (realFlags & flag) > 0) { // in latest versions this bug is fixed, so we're checking is bug exists. r.seek(7); flag = (~flag & 0xff); // removing only wrong bit, other bits remains the same. r.write(realFlags & flag); } r.close(); } 

Versión actualizada :

El código siguiente elimina todos los bytes incorrectos en ZIP. KMPMatch.java fácil de encontrar en google

 public static void replaceWrongBytesInZip(File zip) throws IOException { byte find[] = new byte[] { 0, 0x08, 0x08, 0x08, 0 }; int index; while( (index = indexOfBytesInFile(zip,find)) != -1) { replaceWrongZipByte(zip, index + 2); } } private static int indexOfBytesInFile(File file,byte find[]) throws IOException { byte fileContent[] = new byte[(int) file.length()]; FileInputStream fin = new FileInputStream(file); fin.read(fileContent); fin.close(); return KMPMatch.indexOf(fileContent, find); } /** * Replace wrong byte http://sourceforge.net/tracker/?func=detail&aid=3477810&group_id=14481&atid=114481 * @param zip file * @throws IOException */ private static void replaceWrongZipByte(File zip, int wrongByteIndex) throws IOException { RandomAccessFile r = new RandomAccessFile(zip, "rw"); int flag = Integer.parseInt("00001000", 2); r.seek(wrongByteIndex); int realFlags = r.read(); if( (realFlags & flag) > 0) { // in latest versions this bug is fixed, so we're checking is bug exists. r.seek(wrongByteIndex); flag = (~flag & 0xff); // removing only wrong bit, other bits remains the same. r.write(realFlags & flag); } r.close(); } 
  • Convertir apk en zip flashable en clockWorkMod?
  • Archivo zip con memoria en Java
  • Archivo sin conexión de Osmdroid
  • Compresión de datos en Android (aparte de java.util.zip?)
  • Descomprimir archivo en activos de Android
  • Cómo android almacena y ejecuta programas
  • ¿Cómo comprimir archivos zip con contraseña (AES) para iOS y Android?
  • XAPK La validación de archivos muestra los datos correctos Información
  • Android Descargar Zip a la tarjeta SD?
  • ¿Es posible mostrar svgz en Android?
  • Cómo crear un ZIP InputStream en Android sin crear primero un archivo ZIP?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.