Alguem aqui consegui usar o algoritmo de Huffman? Tenho uma frase que após compactar e descompactar ela muda em alguns caracteres, devo estar fazendo algo de errado.
Possuo 2 TextArea, o TextArea possui a mesagem a ser compactada e o TextArea1 mostra a mensagem compactada.
Estou usando esta biblioteca http://www.icewalkers.com/Linux/Software/57430/Huffman-java.html
private void compactar() {
if (textArea.getText().length() > 0) {
temp = System.currentTimeMillis();
Huffman huf = new Huffman();
byte[] saida = new byte[textArea.getText().getBytes().length];
vet = new int[Huffman.ALPHABETSIZE];
huf.compress(textArea.getText().getBytes(), saida, vet);
textArea1.setText(new String(saida));
label3.setText(((saida.length) / 1024) + " Kb");
temp = (System.currentTimeMillis() - temp);
tempo.setText(new SimpleDateFormat("mm:ss:SSS").format(new Date(temp)));
button1.setText("Descompactar");
}
}
private void descompactar() {
if (textArea1.getText().length() > 0) {
temp = System.currentTimeMillis();
Huffman des = new Huffman();
byte[] saida = new byte[textArea.getText().getBytes().length];
des.uncompress(textArea1.getText().getBytes(), saida, vet);
textArea.setText(new String(saida));
temp = (System.currentTimeMillis() - temp);
tempo.setText(new SimpleDateFormat("mm:ss:SSS").format(new Date(temp)));
button1.setText("Compactar");
}
}
Algue tem uma ideia de como resolver isso? Obrigado!
Um array de bytes não pode ser convertida diretamente em uma string, a menos que tenha origem na codificação de outra string corretamente formada. O que ocorre é que certos bytes, quando convertidos com “new String(byte[])”, são convertidos para o caracter ‘?’ (ponto de interrogação).
O que ocorreu no seu caso é que você passou os bytes para uma string, e depois tentou recuperá-los de volta. Isso bagunçou alguns bytes, o que foi suficiente para confundir o descompressor Huffman. Portanto o problema não é com o algoritmo e sim com o fato que não se pode guardar bytes em uma String.
O que se pode fazer é converter os bytes para uma String usando a codificação base-64 (que aumenta os dados de 33%) ou então nunca passar os bytes para uma string.
HUm, boa cara deu certo aqui, vou deixar sem mexer no vetor de byte assim ganho em compactação, do outro jeito tb deu certo mas como vc disse aumenta um pouco o tamanho, valeu pela dica!
Cara surgiu uma nova duvida, pelo o que eu vi neste algoritmo ele diminui e bastante o tamanho do texto, mas para descompactar preciso ter o valor da arvore binaria correto? se isso for verdade nos meus calculos, se eu compactar uma frase “teste de compactação”, na hora de transmitir se eu unir o tamanho do texto codificado mais a arvore binaria pois preciso passar ela junto, o tamanho final vai ser maior que se eu passar a frase direto, tah correto isso ou estou fazendo algo errado?
Sim senhor. É por isso que o algoritmo de Huffman, sozinho, não resolve os problemas.
Os algoritmos LZalgumacoisa tratam justamente desse problema de “como codificar o dicionário, de forma que ele não fique tão grande quanto os dados originais”.
Variações dos algoritmos LZ (como o DEFLATE, que é usado na ZLIB - java.util.zip.Deflater/Inflater) também aceitam dicionários pré-definidos, para que você não precise codificar o dicionário.
Hum, cara então no meu caso que quero transferir uma mensagem de uma forma compactada, e no destino descompacta-la qual seria a melhor forma de se fazer isso?
Use o algoritmo ZLIB mesmo, que já vem no Java e vem super-otimizado (tipicamente é implementado como código nativo).
As classes são “java.util.zip.Deflater” e “java.util.zip.Inflater”.
Valeu cara vou ver como utiliza-los, aproveitando tu sabe algo de criptografia? Gostaria de aplicar algum tipo de criptografica nestes valores compactados.
Se você olhar o BouncyCastle ( http://www.bouncycastle.org ) , você vai descobrir que existe um formato de dados chamado PKCS#7 que aceita opcionalmente compressão sobre os dados. (As classes são CMSalgumacoisa - CMS = Cryptographic Message Syntax, um outro nome do PKCS#7).
Além disso, se seus dados têm de ser trafegados via sockets, você pode usar o velho e bom SSL (que tem suporte razoável diretamente no Java).
Na verdade preciso compactar e criptografar mas nada muito exagerado, pois vai ser feito em um palm, e o destino vai ser direto em uma packge em oracle, entao nao posso viajar muito nos algoritmos ahuahua pode funcionar no Java mas chegando no oracle posso ter problemas.
Vc me aconselha a primeiro compactar com o Deflater e depois usar o PKCS ou fazer tudo com o PKCS já que ele compacta e criptografa?
Palm? Então você precisa ver o que está disponível no Java que você vai usar. Lembre-se que o Java do Palm é bem mais limitado, nem sei se há a classe java.util.zip.* para você usar. De qualquer maneira, várias das classes do BouncyCastle podem ser usadas no JavaME.
Além disso, você vai guardar os dados comprimidos e criptografados no Oracle ou você precisa decifrá-los e descomprimi-los antes de chegarem ao Oracle?
MD5 não é criptografia, é hash, e no seu caso (em que você precisa “reverter” a criptografia) você não pode usar MD5.
No oracle terei que desfazer tudo para gravar os dados, em relaçao as bibliotecas no palm eu consigo coloca-las na JVM, na parte Oracle estava pensando em descriptogravar e descompactar usando Java mesmo, sendo que oracle aceita codigo java nativo.
Bom, você terá de usar no Oracle as classes adequadas para descompressão e criptografia (que estão em java.util.zip.* e javax.crypto.* respectivamente). Mas na JVM do Palm é que não sei se a java.util.zip.* está disponível.
De qualquer maneira, eu não recomendaria você criar uma classe de compressão de dados, nem de criptografia, já que são duas coisas difíceis de fazer direito e que devem ser deixadas para profissionais dessas áreas.
O Deflater é uma classe que normalmente chama código nativo, pelo menos nas implementações do JDK que conheço. É por isso que normalmente você não vê essa classe implementada em qualquer versão de JavaME. (E é por isso que não adianta “jogar a classe no Palm”. )
Ae cara rodou, certinho no pocket pc, agora preciso pensar em uma forma de passar este array de bits direto para meu webservice e ele passar pro Oracle, se eu for passar este array para string vou perde precisao e dar pau depois na ora de converter, e passar um objeto array debytes direto creio que nao dá, tem alguma ideia a respeito? Valeu!
Normalmente você converte os bytes para Base-64. No Oracle você pode desconverter usando uma classe do JDK (sun.misc.Base64Decoder) e no Palm (ou é PocketPC?) você usa uma classe qualquer do BouncyCastle (por exemplo).
Sim uso Pocket PC, na verdade fiz uma mistura para dar certo, estou usando J9 da IBM e adicionar as bibliotecas da CrEME nela, como a CrEME já dá suporte a java.util nao precisei fazer nada pois já estava dando suporte.