Cara, XML num codigo de barras foi novidade
Como eh esse XML? Que dados vc realmente tem que passar?
Cara, XML num codigo de barras foi novidade
Como eh esse XML? Que dados vc realmente tem que passar?
EDI = Electronic Data Interchange
Esse é um nome genérico para os protocolos usados para troca de dados antes que o XML fosse inventado. Esses protocolos são do tempo em que a gente usava só 2 dígitos para o ano, para não gastar espaço à toa, e que compressão de dados não existia. (A rigor existia sim - quem usou mainframes IBM há 20 anos atrás lembra-se do programa ‘hpack’ - , mas era patenteado e muito caro)
Exemplos de protocolos EDI: EDIFACT, etc.
Esses protocolos são muito chatos, descritivos e bitolados; muita gente ainda ganha direito fazendo “tradutores EDI” ou “EDI mappers” que são bibliotecas que convertem um formato EDI em outro.
No seu caso, só valeria a pena se um dos lados requer que os dados venham em formato padrão EDIFACT (por exemplo).
Só que EDIFACT e outros protocolos não efetuam compressão - a rigor, se você vir uma mensagem EDIFACT, não só não vai entender nada, como vai achar que tem algum espaço desperdiçado.
O equivalente desses protocolos EDI hoje em dia é o ebXML e o BizTalk.
Sem cair nos protocolos e formatos de dados da epoca do guarana com rolha de cortica, voce pode usar o bom e velho CSV caso seu documento nao precise de estrutura hierarquica, ou se a hierarquia for facil de “remontar” a partir de uma sequencia do tipo
Nome,Tel1,Tel2,Tel3
Carlos,5551234,5554321,5551324
Eduardo,5556789,5559876,5556879
Isso evita que vc sequer tenha que fazer mta compressao, pq vc ja desperdica pouco espaco em primeiro lugar. Passar um gzip num arquivo assim dexa ele ridiculamente pequeno… mas talvez nao tanto a ponto de caber num codigo de barras…
Quantos bytes voce pode gastar, no total?
Bom, eu estou pensando pelo menos no código de barras, fazer algo do tipo csv mesmo pra economizar espaço… Uma outra alternativa seria alterar o código de barras de pdf417 para supercode, que comporta mais caracteres, ao redor de 4000. Mas uma coisa que não estou entendendo, é que nas documentações do PDF417 que li, informa-se 2710 caracteres alfanuméricos máximos, porém, só consigo colocar bem menos que isso… O problema é que não há muita documentação do supercode pela internet, já o pdf417 já é mais padronizado. Ah, uma dúvida, tentei comprimir um arquivo pequeno, em torno de 10 bytes usando o algoritmo Deflater e acabou aumentando o tamanho do arquivo, assim como ocorreu quando eu tentei comprimir a assinatura digital do mesmo…
Bom, dados que não podem ser comprimidos com sucesso:
Dados muito pequenos (como é o caso dos seus 10 bytes);
Dados quase-aleatórios (como é o caso das assinaturas digitais, que aparentam ser dados “quase-aleatórios” - o nome técnico é “de alta entropia” - basta examinar o dump hexadecimal de uma assinatura para ver que há muitos lugares onde não é possivel enxergar seqüências repetidas ou previsíveis.)
Se você tiver uma imagem escaneada mas não comprimida - por exemplo, um BMP ou um TIFF sem compressão - , também terá algo que ao ser examinado com um dump hexadecimal parece um pouco aleatório (ao tentar comprimir uma figura dessas usando zip você não vai obter uma boa taxa de compressão.) É necessário perder alguma informação (“lossy compression”) para poder comprimir uma imagem.
Agora, não estou conseguindo descomprimir, não sei o q está havendo…
Aqui está o código:
public class Compressao
{
public static byte[] comprime( byte[] bytes ) throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DeflaterOutputStream dos = new DeflaterOutputStream( baos, new Deflater( Deflater.BEST_COMPRESSION ) );
dos.write( bytes );
dos.flush();
dos.close();
return baos.toByteArray();
}
public static byte[] decomprime( byte[] arrayComprimido ) throws DataFormatException
{
Inflater decompressor = new Inflater();
decompressor.setInput( arrayComprimido );
byte[] saida = new byte[4096];
int tamanhoResultado = decompressor.inflate( saida );
decompressor.end();
byte[] byteFinal = new byte[tamanhoResultado];
System.arraycopy( saida, 0, byteFinal, 0, tamanhoResultado );
return byteFinal;
}
}
Também já tentei usar InflaterInputStream, mas não consegui… Ocorre a seguinte exceção:
java.util.zip.DataFormatException: incorrect data check
at java.util.zip.Inflater.inflateBytes(Native Method)
at java.util.zip.Inflater.inflate(Unknown Source)
at java.util.zip.Inflater.inflate(Unknown Source)
at ecfv.util.Compressao.decomprime(Compressao.java:33)
at ecfv.cliente.Cliente$2.run(Cliente.java:561)
at java.lang.Thread.run(Unknown Source)
usando deflate, bzip2 ou qualquer outro método aritmético com um volume de dados tão pequeno (2400 bytes) vai ser MUITO dificil conseguir uma taxa de compressão superior a atual sem “roubar” e usar compressores especializados.
Existem algumas formas boas de “roubar” que vão melhorar a taxa de compressão e explodir o número de horas do teu projeto, via de regra você pode fazer as seguintes coisas (em ordem progressiva de dificuldade):
1)Pré-condicionar os seus dados para melhorar a compressão, isso envolve saber primeiro como funciona os algoritmos da classe lzw. Nessa etapa vão ser feitas transformações com dicionarios estáticos ou que diminua a entropia usada pelo modelo do lzw (translação, transformações afins, re-codificação, troca de base, etc)
2)Gerar algumas tabelas de símbolos do lwz que sejam as mais comuns pros teus dados, coloca elas como dados externos, modificar as classes de zip para o stream gerado incluir uma referencia para essas tabelas em vez delas e o compressor usar uma das tabelas.
3)Desistir de conseguir mais que o atual e rever os requisitos do projeto. Você pode calcular a entropia do XML gerado e provar matemáticamente pro teu chefe que você já está próximo demais do limite de compressão que é, científicamente possivel de provar, o menor.
Simples, né?
bom, eu sugeri ao meu chefe utilizarmos dois códigos de barras ao invés de apenas um, então um ficaria com a chave publica e a assinatura e o outro código de barras conteria o xml…
pro primeiro código eu criaria um grande array de bytes, tendo a chave separada da assinatura por um token de 3 bytes…, sendo a chave comprimida individualmente… blz, o token é criado, o problema eh que ele não consegue extrair os dados, no dump hexadecimal que eu fiz, está tudo correto…
Aqui vai o codigo…
public static byte[] criaArrayInformacoes( byte[][] conteudo )
{
int tamanhoToken = ECFVClienteConstants.TOKEN.length;
int[] tamanhoElementos = new int[ conteudo.length ];
for ( int i = 0; i < conteudo.length; i++ )
tamanhoElementos[i] = conteudo[i].length;
int tamanhoTotal = 0;
for ( int i = 0; i < tamanhoElementos.length; i++ )
tamanhoTotal += tamanhoElementos[i];
if ( !( tamanhoElementos.length == 1 ) )
tamanhoTotal += tamanhoToken * ( tamanhoElementos.length - 1 );
byte[] arrayTudo = new byte[ tamanhoTotal ];
int indiceAtual = 0,
indiceFinal = conteudo.length;
for ( int i = 0; i < indiceFinal; i++ ) {
System.arraycopy( conteudo[i], 0, arrayTudo, indiceAtual, tamanhoElementos[i] );
indiceAtual += tamanhoElementos[i];
if ( !( i == indiceFinal - 1 ) ) {
System.arraycopy( ECFVClienteConstants.TOKEN, 0, arrayTudo, indiceAtual, tamanhoToken );
indiceAtual += tamanhoToken;
}
}
return arrayTudo;
}
public static byte[][] extraiInformacoes( byte[] array )
{
String str = new String( array );
Pattern reg = Pattern.compile( new String( ECFVClienteConstants.TOKEN ) );
String[] arrStr = reg.split( str );
byte[][] b = new byte[ arrStr.length ][];
for ( int i = 0; i < b.length; i++ )
b[i] = arrStr[i].getBytes();
return b;
}
to há um tempao nisso e nao consegui resolver ainda…