Descompactar arquivo grande sem perder dados

2 respostas
collinsjws

Olá,

Estou usando um método para descompactar arquivos zip com senha que peguei neste endereço: http://java.sys-con.com/node/1258827 e estou com o seguinte problema:

Faço o método descompactar um arquivo zipado que contém um arquivo .txt de 300 mb com 1.323.008 linhas e quando o processo termina, o arquivo .txt tem apenas 64 linhas. Não gera erro algum. Apenas traz o txt "quase nú".

Ah! para rodar este método precisa de dois jars: o sevenzipjbinding e o sevenzipjbinding-AllPlatforms

O código está abaixo:

@SuppressWarnings("CallToThreadDumpStack")
    public static void extrairZipComSenha(final String arquivoZipadoComSenha, final String diretorioDestino, final String senha) {
        RandomAccessFile randomAccessFile = null;
        ISevenZipInArchive inArchive = null;
        try {
            randomAccessFile = new RandomAccessFile(arquivoZipadoComSenha, "r");
            inArchive = SevenZip.openInArchive(null, // autodetect archive type
                    new RandomAccessFileInStream(randomAccessFile));
            // Getting simple interface of the archive inArchive
            ISimpleInArchive simpleInArchive = inArchive.getSimpleInterface();
            for (final ISimpleInArchiveItem item : simpleInArchive.getArchiveItems()) {
                final int[] hash = new int[]{0};
                if (!item.isFolder()) {
                    ExtractOperationResult result;
                    result = item.extractSlow(new ISequentialOutStream() {

                        @Override
                        @SuppressWarnings("CallToThreadDumpStack")
                        public int write(final byte[] data) throws SevenZipException {
                            try {
                                if (item.getPath().indexOf(File.separator) > 0) {
                                    String path = diretorioDestino + File.separator + item.getPath().substring(0, item.getPath().lastIndexOf(File.separator));
                                    File folderExisting = new File(path);
                                    if (!folderExisting.exists()) {
                                        new File(path).mkdirs();
                                    }
                                }
                                OutputStream out = new FileOutputStream(diretorioDestino + File.separator + item.getPath());
                                out.write(data);
                                out.close();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            hash[0] |= Arrays.hashCode(data);
                            return data.length; // Return amount of proceed data
                        }
                    }, senha); /// password.
                    if (result == ExtractOperationResult.OK) {
                        System.out.println(String.format("%9X | %s",
                                hash[0], item.getPath()));
                    } else {
                        System.err.println("Error extracting item: " + result);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (inArchive != null) {
                try {
                    inArchive.close();
                } catch (SevenZipException e) {
                    System.err.println("Error closing archive: " + e);
                    e.printStackTrace();
                }
            }
            if (randomAccessFile != null) {
                try {
                    randomAccessFile.close();
                } catch (IOException e) {
                    System.err.println("Error closing file: " + e);
                    e.printStackTrace();
                }
            }
        }
    }

2 Respostas

E

Se você observou o que ocorreu, deve ter visto que o arquivo destino foi aberto, escrito e fechado algumas milhares de vezes, não? Por que é que se sobreescreve o método “write”?

collinsjws

Olá,

Depois de muito bater cabeça, acabei resolvendo o problema de outra forma. Deixei o método apresentado anteriormente de lado, pois não consegui fazê-lo funcionar corretamente.

Resolvi utilizando uma linha de comando do 7-zip e executando o mesmo pelo java.
Para usar o mesmo você precisa baixar a versão do 7-zip para linhas de comando. Para ajudar, estou colocando a mesma em anexo neste post.

O exemplo ta no código abaixo:

public void extrairZipComandoComSenha(String arquivo, String senha, String diretorio) {
        try {
            Process p = Runtime.getRuntime().exec("7za x " + arquivo + " -p" + senha + " -o" + diretorio + "");
            p.waitFor();
        } catch (InterruptedException ex) {
            Logger.getLogger(Zipper.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Zipper.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

A chamada dele é a seguinte:

extrairZipComandoComSenha("C:\\temp\\arquivo.zip", "dgjk54dg345", "C:\\temp2");

obs.: Os parâmetros utilizados aqui são fictícios.

No meu caso, os arquivos são bem grandes (300mb em média) e com senhas. Com essa solução eu não perco dados, como acontecia anteriormente.

Bom, espero poder ajudar a quem tiver o mesmo problema. Qualquer coisa pode me procurar.

Abraço a todos

Criado 31 de agosto de 2010
Ultima resposta 2 de set. de 2010
Respostas 2
Participantes 2