2008-10-28 33 views
11

Cuando creo un archivo zip a través de java.util.zip.*, ¿hay alguna manera de dividir el archivo resultante en varios volúmenes?¿Cómo dividir un archivo zip enorme en varios volúmenes?

Digamos que mi archivo general tiene un filesize de 24 MB y quiero dividirlo en 3 archivos con un límite de 10 MB por archivo.
¿Hay una API zip que tenga esta característica? ¿O alguna otra buena manera de lograr esto?

Gracias Thollsten

Respuesta

7

Comprobar: http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=38&t=004618

No estoy al tanto de cualquier API pública que le ayudará a hacer eso. (Aunque si no desea hacerlo mediante programación, hay utilidades como WinSplitter que lo hará)

Yo no lo he probado, pero, cada ZipEntry durante el uso de ZippedInput/OutputStream tiene un tamaño comprimido. Puede obtener una estimación aproximada del tamaño del archivo comprimido al crearlo. Si necesita 2MB de archivos comprimidos, puede dejar de escribir en un archivo después de que el tamaño acumulado de las entradas se convierta en 1.9MB, tomando .1MB para el archivo Manifiesto y otros elementos específicos del archivo zip. Así, en pocas palabras, puede escribir un envoltorio sobre el ZippedInputStream de la siguiente manera:

import java.util.zip.ZipOutputStream; 
import java.util.zip.ZipEntry; 
import java.io.FileOutputStream; 
import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.IOException; 

public class ChunkedZippedOutputStream { 

    private ZipOutputStream zipOutputStream; 

    private String path; 
    private String name; 

    private long currentSize; 
    private int currentChunkIndex; 
    private final long MAX_FILE_SIZE = 16000000; // Whatever size you want 
    private final String PART_POSTFIX = ".part."; 
    private final String FILE_EXTENSION = ".zip"; 

    public ChunkedZippedOutputStream(String path, String name) throws FileNotFoundException { 
     this.path = path; 
     this.name = name; 
     constructNewStream(); 
    } 

    public void addEntry(ZipEntry entry) throws IOException { 
     long entrySize = entry.getCompressedSize(); 
     if((currentSize + entrySize) > MAX_FILE_SIZE) { 
      closeStream(); 
      constructNewStream(); 
     } else { 
      currentSize += entrySize; 
      zipOutputStream.putNextEntry(entry); 
     } 
    } 

    private void closeStream() throws IOException { 
     zipOutputStream.close(); 
    } 

    private void constructNewStream() throws FileNotFoundException { 
     zipOutputStream = new ZipOutputStream(new FileOutputStream(new File(path, constructCurrentPartName()))); 
     currentChunkIndex++; 
     currentSize = 0; 
    } 

    private String constructCurrentPartName() { 
     // This will give names is the form of <file_name>.part.0.zip, <file_name>.part.1.zip, etc. 
     StringBuilder partNameBuilder = new StringBuilder(name); 
     partNameBuilder.append(PART_POSTFIX); 
     partNameBuilder.append(currentChunkIndex); 
     partNameBuilder.append(FILE_EXTENSION); 
     return partNameBuilder.toString(); 
    } 
} 

El programa anterior es sólo un indicio del enfoque y no una solución definitiva por cualquier medio.

+1

Esto es solo varios archivos zip separados, ¿verdad? No es un solo archivo zip de varios volúmenes. – mcv

+0

Tenemos este código trabajando en las respuestas a esta pregunta - http://stackoverflow.com/questions/11104889/how-to-create-java-zip-archives-with-a-max-file-size-limit –

5

Si el objetivo es que la salida sea compatible con pkzip y winzip, no conozco ninguna biblioteca de código abierto que haga esto. Tuvimos un requisito similar para una de nuestras aplicaciones, y terminé escribiendo nuestra propia implementación (compatible con el estándar zip). Si recuerdo, lo más difícil para nosotros fue que tuvimos que generar los archivos individuales sobre la marcha (la forma en que funcionan la mayoría de las utilidades zip es que crean el archivo zip grande, luego lo regresan y lo dividen más tarde, es mucho más fácil implementar. Tomó alrededor de un día para escribir y 2 días para depurar.

El zip estándar explica cómo debe verse el formato de archivo. Si no tiene miedo de arremangarse un poco, esto es definitivamente factible. Tienes que implementar un generador de archivos zip tú mismo, pero puedes usar la clase Deflator de Java para generar las secuencias de segmentos para los datos comprimidos. Tendrás que generar los encabezados de archivos y secciones tú mismo, pero solo son bytes, nada demasiado difícil. una vez que te sumerjas.

Aquí está la zip specification - sección K tiene la información que está buscando específicamente, pero también necesitará leer A, B, C y F. Si está tratando con archivos realmente grandes (Nosotros lo éramos), también tendrá que usar Zip64, pero por 24 MB, está bien.

Si quieres bucear y probarlo, si te surgen dudas, publícalo y veré si puedo proporcionar algunos consejos.

+0

I Tengo problemas con los archivos zip de varios volúmenes. Específicamente cuando un único componente de archivo se divide entre más que el archivo de disco. En file.zx01 tengo el encabezado del archivo y la primera parte de los datos comprimidos, luego en file.zx02 tengo el resto de los datos comprimidos.Pero no puedo volver a armar los archivos por alguna razón, y no estoy seguro de por qué. ¿Tienes alguna experiencia aquí? – vy32

Cuestiones relacionadas