Compactar arquivo na memória

7 respostas
A

Amigos,
Java possui uma ou mais classes para compactar arquivos.

É possível compactar um arquivo apenas em memória do computador, sem gravá-lo no disco?

A intenção é compactar um arquivo texto selecionado pelo usuário, mantendo o arquivo compactado na memória do PC, transmitir esse arquivo compactado utilizando socket e depois descartá-lo da memória, sem ter que criar provavelmente uma pasta e um arquivo físico na máquina do usuário.

7 Respostas

K

Opa, você sempre pode armazenar o conteúdo do arquivo (compactado ou não) como um array de bytes.
Dado que as classes de compactação usam InputStream e OutputStream, talvez você possa usar as implementações ByteArrayInputStream e ByteArrayOutputStream pra quebrar este galho pra você em memória.

A

kicolobo:
Opa, você sempre pode armazenar o conteúdo do arquivo (compactado ou não) como um array de bytes.
Dado que as classes de compactação usam InputStream e OutputStream, talvez você possa usar as implementações ByteArrayInputStream e ByteArrayOutputStream pra quebrar este galho pra você em memória.

Valeu pela dica!

Você consegue dar uma pequena demonstração via código?

B
package guj;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;

public class ExemploCompressaoArquivos {

    public void comprimirParaArquivo(String arqEntrada, String arqSaida) throws IOException {
        GZIPOutputStream gzos = null;
        BufferedInputStream bis = null;
        byte[] buffer = new byte[8 * 1024];
        try {
            int nBytes;
            bis = new BufferedInputStream(new FileInputStream(arqEntrada));
            gzos = new GZIPOutputStream(new BufferedOutputStream(new FileOutputStream(arqSaida)));
            while ((nBytes = bis.read(buffer)) > 0)
                gzos.write(buffer, 0, nBytes);
        } finally {
            gzos.close();
            bis.close();
        }
    }

    public byte[] comprimirParaMemoria(String arqEntrada) throws IOException {
        GZIPOutputStream gzos = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        BufferedInputStream bis = null;
        byte[] buffer = new byte[8 * 1024];
        try {
            int nBytes;
            bis = new BufferedInputStream(new FileInputStream(arqEntrada));
            gzos = new GZIPOutputStream(baos);
            while ((nBytes = bis.read(buffer)) > 0)
                gzos.write(buffer, 0, nBytes);
        } finally {
            gzos.close();
            bis.close();
        }
        return baos.toByteArray();
    }

    /**
     * @param args
     */
    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        ExemploCompressaoArquivos eca = new ExemploCompressaoArquivos();
        eca.comprimirParaArquivo(args[0], args[1]);
        byte[] bytes = eca.comprimirParaMemoria(args[0]);
        System.out.println(bytes.length); // confronte com o arquivo de saída para ver se ficou do mesmo tamanho
    }

}

Use gzip -d para descompactar o arquivo gerado e ver se ele bate com o original.

A
bezier curve:
package guj;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;

public class ExemploCompressaoArquivos {

    public void comprimirParaArquivo(String arqEntrada, String arqSaida) throws IOException {
        GZIPOutputStream gzos = null;
        BufferedInputStream bis = null;
        byte[] buffer = new byte[8 * 1024];
        try {
            int nBytes;
            bis = new BufferedInputStream(new FileInputStream(arqEntrada));
            gzos = new GZIPOutputStream(new BufferedOutputStream(new FileOutputStream(arqSaida)));
            while ((nBytes = bis.read(buffer)) > 0)
                gzos.write(buffer, 0, nBytes);
        } finally {
            gzos.close();
            bis.close();
        }
    }

    public byte[] comprimirParaMemoria(String arqEntrada) throws IOException {
        GZIPOutputStream gzos = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        BufferedInputStream bis = null;
        byte[] buffer = new byte[8 * 1024];
        try {
            int nBytes;
            bis = new BufferedInputStream(new FileInputStream(arqEntrada));
            gzos = new GZIPOutputStream(baos);
            while ((nBytes = bis.read(buffer)) > 0)
                gzos.write(buffer, 0, nBytes);
        } finally {
            gzos.close();
            bis.close();
        }
        return baos.toByteArray();
    }

    /**
     * @param args
     */
    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        ExemploCompressaoArquivos eca = new ExemploCompressaoArquivos();
        eca.comprimirParaArquivo(args[0], args[1]);
        byte[] bytes = eca.comprimirParaMemoria(args[0]);
        System.out.println(bytes.length); // confronte com o arquivo de saída para ver se ficou do mesmo tamanho
    }

}

Use gzip -d para descompactar o arquivo gerado e ver se ele bate com o original.

Obrigado pela ajuda.

Acabei utilizando o método abaixo que utiliza as classes Zip.

// Compacta arquivo na memória
    public byte[] compactarArquivo(String arqEntrada) throws IOException {
        int cont;
        byte[] dados = new byte[4096];

        BufferedInputStream origem;
        FileInputStream streamDeEntrada;
        ByteArrayOutputStream destino;
        ZipOutputStream saida;
        ZipEntry entry;

        try {
            destino = new ByteArrayOutputStream();
            saida = new ZipOutputStream(new BufferedOutputStream(destino));
            File f = new File(arqEntrada);
            streamDeEntrada = new FileInputStream(f);
            origem = new BufferedInputStream(streamDeEntrada, 4096);
            entry = new ZipEntry(f.getName());
            saida.putNextEntry(entry);

            while ((cont = origem.read(dados, 0, 4096)) != -1) {
                saida.write(dados, 0, cont);
                notificarObservadores(Util.PROCESSANDO);
            }
            origem.close();
            saida.close();
            return destino.toByteArray();
        } catch (IOException e) {
            throw new IOException(e.getMessage());
        }
    }
E

Isso é má prática. A mensagem de erro é uma das coisas menos informativas de uma exceção (esse tipo de coisa que você fez destrói o stack trace, por exemplo).
Em vez disso, simplesmente não ponha um try/catch (já que você disse que seu método “throws IOException”) ou então faça algo como:

} catch (IOException e) {  
        // faça alguma coisa interessante, e então:
        throw e;
    }
A

entanglement:

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

Isso é má prática. A mensagem de erro é uma das coisas menos informativas de uma exceção (esse tipo de coisa que você fez destrói o stack trace, por exemplo).
Em vez disso, simplesmente não ponha um try/catch (já que você disse que seu método “throws IOException”) ou então faça algo como:

} catch (IOException e) {  
        // faça alguma coisa interessante, e então:
        throw e;
    }

Valeu pela sugestão.

Eu copiei o código faz algum tempo da internet e fui alterando alguma coisa.

O que seria melhor? Manter ou tirar o try/catch?

E

Veja o código do Bezier Curve (ele usou um try/finally para forçar o fechamento dos arquivos. )
Não se esqueça: tudo que abriu, feche. Toalha molhada? Não é para largar em cima da cama e sim no cabide ou no varal.

Criado 22 de janeiro de 2013
Ultima resposta 23 de jan. de 2013
Respostas 7
Participantes 4