Put files inside a. zip file

Asked

Viewed 1,501 times

3

I have a class where I compress some files:

public class CompactarArquivo {

    //Constante
    static final int TAMANHO_BUFFER = 4096; // 4kb

    //método para compactar arquivo
    public static void compactarParaZip(String arqSaida, String arqEntrada, String arqEntrada1)
            throws IOException {

        FileOutputStream destino;
        ZipOutputStream saida;

        try {
            destino = new FileOutputStream(new File(arqSaida));
            saida = new ZipOutputStream(new BufferedOutputStream(destino));

            add(arqEntrada, saida);
            add(arqEntrada1, saida); 

            saida.close();

        } catch (IOException e) {
            throw new IOException(e.getMessage());
        }
    }

    private static void add(String arquivo, ZipOutputStream saida) throws IOException {
        int cont;
        byte[] dados = new byte[TAMANHO_BUFFER];

        File file = new File(arquivo);
        BufferedInputStream origem = new BufferedInputStream(new FileInputStream(file), TAMANHO_BUFFER);
        ZipEntry entry = new ZipEntry(file.getName());
        saida.putNextEntry(entry);

        while ((cont = origem.read(dados, 0, TAMANHO_BUFFER)) != -1) {
            saida.write(dados, 0, cont);
        }

        origem.close();
    }

In this class I get two files and I get one .zip. But I’d like to open this file .zip later and add more files inside it. How do I solve this problem?

2 answers

3

I found a tutorial in English and did his translation and test. To insert files into a ZIP file you must use the NIO library, present in Java 7 or higher.

    Map<String, String> zip_properties = new HashMap<>();

    /* Se o arquivo ZIP já existe, coloque false*/
    zip_properties.put("create", "false");

    zip_properties.put("encoding", "UTF-8");

    Path path = Paths.get("C:\\Temp\\Arquivos.zip");

    /* Especifique o caminho para o arquivo zip que você quer ler como um sistema de arquivos */
    URI zip_disk = URI.create("jar:" + path.toUri());

     /* Cria o Sistema de arquivo ZIP */
    try (FileSystem zipfs = FileSystems.newFileSystem(zip_disk, zip_properties)) {

        /* Cria o arquivo dentro do ZIP*/
        Path ZipFilePath = zipfs.getPath("footer.html");

        /* Caminho do arquivo que deve ser adicionado */
        Path addNewFile = Paths.get("C:\\Temp\\footer.html");

        Files.copy(addNewFile, ZipFilePath);
    }

Before the execution of the codeinserir a descrição da imagem aqui

After the execution of the code inserir a descrição da imagem aqui

The . html file I put inside the zip was not corrupted.

Source: http://thinktibits.blogspot.com.br/2013/02/Add-Files-to-Existing-ZIP-Archive-in-Java-Example-Program.html

1


If you are using a version earlier than Java 7, the best way to do this is to unzip the files inside the .zip and play along with the new files in a new .zip.

Based in Soen’s reply.

private static void addFilesToZip(File source, File[] files, String path){
    try{
        File tmpZip = File.createTempFile(source.getName(), null);
        tmpZip.delete();

        if(!source.renameTo(tmpZip)){
            throw new Exception("Não foi possível criar o arquivo temporário (" + source.getName() + ")");
        }

        byte[] buffer = new byte[TAMANHO_BUFFER];
        ZipInputStream zin = new ZipInputStream(new FileInputStream(tmpZip));
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(source));

        for(int i = 0; i < files.length; i++){
            InputStream in = new FileInputStream(files[i]);
            out.putNextEntry(new ZipEntry(path + files[i].getName()));                
            for(int read = in.read(buffer); read > -1; read = in.read(buffer)){
                out.write(buffer, 0, read);
            }                
            out.closeEntry();
            in.close();
        }

        for(ZipEntry ze = zin.getNextEntry(); ze != null; ze = zin.getNextEntry()){
            if(!zipEntryMatch(ze.getName(), files, path)){
                out.putNextEntry(ze);
                for(int read = zin.read(buffer); read > -1; read = zin.read(buffer)){
                    out.write(buffer, 0, read);
                }
                out.closeEntry();
            }
        }
        out.close();
        tmpZip.delete();
    }catch(Exception e){
        e.printStackTrace();
    }
}

private static boolean zipEntryMatch(String zeName, File[] files, String path){
    for(int i = 0; i < files.length; i++){
        if((path + files[i].getName()).equals(zeName)){
            return true;
        }
    }
    return false;
}

This second method checks if there is no file with the same name inside the Zip. Obviously this needs to be improved, but it is already a good starting point.

If you are using Java 7. You can use the library java. and do so (Example taken from here)

private static void addNoZipExistente(String arqZip, String arqInserir, String nomeArquivoNoZip){       
    Map<String, String> env = new HashMap<>(); 
    env.put("create", "true");

    URI uri = URI.create("jar:" + "file:/" + arqZip.replace("\\", "/"));

    try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) 
    {
        Path arquivoParaInserir = Paths.get(arqInserir);
        Path localNoZip = zipfs.getPath(nomeArquivoNoZip);      

        Files.copy(arquivoParaInserir, localNoZip, StandardCopyOption.REPLACE_EXISTING ); 
    }catch(IOException ioex){
        //Tratar o erro
    }
}

Other than that, I would also change the way you receive the parameters in the method compactarParaZip(), so that it can receive multiple parameters. Maybe you only need two, but this makes the method more dynamic.

public static void compactarParaZip(String arqSaida, String... entradas) throws IOException {

    FileOutputStream destino;
    ZipOutputStream saida;

    try {
        destino = new FileOutputStream(new File(arqSaida));
        saida = new ZipOutputStream(new BufferedOutputStream(destino));

        for(String arq : entradas){
            add(arq, saida);
        }

        saida.close();

    } catch (IOException e) {
        throw new IOException(e.getMessage());
    }
}

An example of how to use it would be

compactarParaZip("novoArquivo.zip", "arq1.txt", "arq2.txt", "arq3.txt");
// posso colocar quantos parâmetros quiser
  • 1

    The two answers would solve the problem, but I chose the @jbueno because it is more complete and explanatory.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.