Problema ao descomprimir String com Inflater

3 respostas
danilogga

Pessoal,

To apanhando aqui com a classe Inflater para descomprimir strings, tenho um programa em VB que comunica via socket com meu programa em java, leio os dados do socket, guardo numa String e tento descomprimir. O problema é que nesse momento que jogo pra dentro de uma String acontece alguma coisa com o array de bytes que não deixa o Inflater descomprir, ele lança a seguinte exception: java.util.zip.DataFormatException: invalid distance code.

Alguém já trabalho com esse Inflater?? fazendo testes aqui eu achei muito estranho, pq cada hora que mudo a mensagem ele dá um erro diferente, dependendo da mensagem ele descomprime de boa, outra hora ele dá “Data check error”, naum consegui entender a lógica desse negócio.

Segue abaixo o código pra ver se alguém consegue dar uma luz.
Vlwww…

import java.util.zip.Deflater;
import java.util.zip.Inflater;

public class Estudo {

	public static void main(String[] args) {
		try {
			// a mensagem que recebo do cliente VB é parecida com essa
			String inputString = "SQL" + (char)11 + "10" + (char)11 + "1234-1234-1234-1234" + (char)11 + "BSB-DSV-35" + (char)1;
			// pega o array de bytes
			byte[] input = inputString.getBytes();

			System.out.println("msg enviada-->" + inputString);
			
			// buffer
			byte[] output = new byte[2000];
			Deflater compresser = new Deflater();
			compresser.setInput(input);
			compresser.finish();
			int compressedDataLength = compresser.deflate(output);

			// o problema acontece aki, quando passo o array output direto pra ser descomprimido ele funciona, quando
			// crio uma string e depois pego o array de bytes com getBytes() ele dá erro
			String msg = new String(output, 0, compressedDataLength);

			System.out.println("msg comprimida-->" + msg);
			
			// pega o array de bytes
			byte[] msgCliente = msg.getBytes();
			// buffer pra descomprimir
			byte[] result = new byte[2000];
			// descomprimindo
			Inflater decompresser = new Inflater();
			decompresser.setInput(msgCliente, 0, compressedDataLength);
			int resultLength = decompresser.inflate(result);
			decompresser.end();
			
			// criando string de saida
			String outputString = new String(result, 0, resultLength);

			System.out.println("msg recebida-->" + outputString + "<--");
		} catch (java.util.zip.DataFormatException ex) {
			ex.printStackTrace();
		}
	}
}

3 Respostas

T

Não guarde um array de bytes dentro de uma string.
É que a conversão (feita por new String()) converte alguns bytes para o caracter ‘?’ (se não me engano, hexadecimal 0x3F).
Experimente criar um array de 256 bytes com os bytes de -128 a +127, e converta-o para uma string.
Você vai ver que cerca de 20 ou 30 dos códigos são convertidos para ‘?’, o que é sumamente desagradável.

Use sempre arrays de bytes todo o tempo; se precisar de algo que possa mudar de tamanho, guarde os bytes acumulados em um ByteArrayOutputStream, e com o método toByteArray, obtenha os bytes acumulados.

danilogga

thingol:
Não guarde um array de bytes dentro de uma string.
É que a conversão (feita por new String()) converte alguns bytes para o caracter ‘?’ (se não me engano, hexadecimal 0x3F).
Experimente criar um array de 256 bytes com os bytes de -128 a +127, e converta-o para uma string.
Você vai ver que cerca de 20 ou 30 dos códigos são convertidos para ‘?’, o que é sumamente desagradável.

Use sempre arrays de bytes todo o tempo; se precisar de algo que possa mudar de tamanho, guarde os bytes acumulados em um ByteArrayOutputStream, e com o método toByteArray, obtenha os bytes acumulados.

O problema é que o cliente me manda String sem compressão antes e depois da mensagem comprimida, ou seja, tenho que receber essa mensagem, remover as strings sem compressão e mandar a string comprimida para a classe Inflater descomprimir. Mas vou verificar se com o ByteArrayOutputStream eu consigo remover alguns itens do array. De qualquer forma valeu pela ajuda…

danilogga

thingol,

Alterei meu programa pra ler direto do socket e guardar num ByteArrayOutputStream como você falou, só que o método socket.read() retorna o código ascii do caracter, se eu naum me engano, ou seja, chega um momento que ele me envia o código 339, e quando adiciono no meu ByteArrayOutputStream ele altera o valor para 83, pois 339 naum cabe em um byte. Como faço pra conseguir jogar ele dentro do ByteArrayOutputStream?

valeu… abraços…

Criado 22 de julho de 2008
Ultima resposta 22 de jul. de 2008
Respostas 3
Participantes 2