Résolu Résolu : Impossible de Compresser/Decompresser une chaine avec java.util.zip

lamathep

Nouveau membre
Bonjour à tous,

Tout d'abord, merci de vous intéresser à mon problème.

Pour info, je suis débutant en Java.

Pour une application android devant transfèrer du texte sur un serveur, il conviendrait de "zipper" les données pour réduire le volume des données transferées. (Usage en 3G, Conso réduite, ou en EDGE, debit réduit, moins de données transitent, plus c'est rapide)

J'ai écumé les forums, docs en tout genre, j'ai fini par trouver quelques exemples de code qui sembleraient ne pas trop mal correspondre à mes besoins.

Je suis parti de celui-ci :


Lorsque j'execute ce code sans mes ajouts, tout va bien, ca compresse, ca décompresse, et l'intégrité des données est bonne.

Losque j'ajoute mon traitement pour convertir les données compressées en chaine (pour qu'elles transitent sur une socket), j'ai l'erreur suivante : "DataFormatException : data error"

Voici mon code, j'espère que vous pourrez m'aider à comprendre ce que j'ai mal fait, ou une solution plus adaptée à mes besoins.

Merci d'avance,
Hugues.

Java:
public static String PG_DEFLATE_INFLATE(String myString)
{
	import java.io.*;
	import java.util.*;
	import java.util.zip.*;

	try {
		// Encode a String into bytes
		byte[] input = myString.getBytes("UTF-8");
		// Compress the bytes
		byte[] output = new byte[100];
		Deflater compresser = new Deflater();
		compresser.setInput(input);
		compresser.finish();
		int compressedDataLength = compresser.deflate(output);
		
		//////////////////////////////////////////////////////////////////////////////////////////////////////
		// "Simulation" d'un passage sur une socket en transformant les données compressées en chaine ////////
		String compressedString = new String(output,0,compressedDataLength);
		byte[] out = compressedString.getBytes();
		// Lors de la décompression, renvoie systematiquement l'exception "DataFormatException : data error"//
		//////////////////////////////////////////////////////////////////////////////////////////////////////
		
		// Decompress the bytes
		Inflater decompresser = new Inflater();
		decompresser.setInput(out, 0, compressedDataLength);
		byte[] result = new byte[100];
		int resultLength = decompresser.inflate(result);
		decompresser.end();
		// Decode the bytes into a String
		String outputString = new String(result, 0, resultLength, "UTF-8");
		
		return outputString;
		
	} catch(java.io.UnsupportedEncodingException ex) {
		return "ERROR[|]"+ex;
	} catch (java.util.zip.DataFormatException ex) {
		return "ERROR[|]"+ex;
	}
}
 
G

Guest

Invité
Le problème se situe a priori ligne 19, le constructeur String va décoder du binaire avec le jeu de caractère par défaut. En clair je pense tu flingues tes données compressée avec ZLIB en faisant cela.

Probablement que si tu compares avec le débuggueur le contenu de "output" et "out" tes tableaux de bytes seront très différents.

Sinon la taille du buffer j'ai pu constater que la valeur de 100 Bytes de l'exemple d'Oracle est un peu faible (si tu boucles par tranches de X Bytes), c'est souvent plus efficace sur un PC généraliste par tranche de 1 Mo (voir plus), sur une plateforme mobile faudra tweaker un peu pour trouver la "bonne" valeur mais c'est aussi probablement un peu faible.
 

lamathep

Nouveau membre
Merci pour ta réponse, je penchais aussi pour quelque chose du genre.

Ma problématique est la suivante :

1) Compresser un texte côté serveur
2) Faire transiter les données compressées sur un réseau via une socket
3) Côté client, décompresser les données pour récupérer mon texte en clair.

Etape 1 et 3 : Ca marche bien.
Etape 2 : La partie socket est développée. Me reste à trouver un moyen de faire transiter un tableau binaire sur une socket. Aurais tu une idée? C'est pour cela que j'avais pensé convertir mon tableau binaire en chaine.
 

KyrO_82

Grand Maître
Salut,
Ouais je doute que tu puisse convertir tes données compressé en string sans pertes. Sur certains langages ça passe (php), mais java j'en doute fort (j'en fais pas moi même). Un string est fait pour contenir du texte, hors de nombreuses valeurs binaire ne corresponde pas à des caractères (0 par ex), donc ne peuvent être stocké par un codage de caractères quelconque.
Comme le dit JohnThePi, suffit de comparer tes buffers output et out.

Mais pourquoi vouloir passer par un string?

Au sujet de la taille du buffer, je m'accord encore une fois avec JohnThePi. Tu n'as jamais de données plus grande que 100 octets, que ce soit compressé ou non?
De plus, ziper des textes de moins de 100 caractères ça sert à rien, tu va au contraire augmenter la taille de tes données (et même peut être fortement).
 

KyrO_82

Grand Maître
Un (une?) socket ne gère que des données binaires, pas du texte. Si tu envoie des strings, alors c'est que ton interface (software) fait la conversion... (logique, mais encore une fois, quel codage? java travail en unicode 32 bit?)

Il ne doit pas avoir de problèmes pour envoyer des tableaux d'octets...
 

lamathep

Nouveau membre
Meilleure réponse
Vos réponses sont sans appel, et l'origine de mes malheurs ne réside donc pas dans Java mais bien dans Windev. (Je suis surpris ...)

Pour info, Windev permet (Visiblement de facon très rudimentaire) d'intégrer du code écrit en java dans ses projets.
Tout ce qui concerne l'execution du code Java en lui même marche bien. C'est lors du passage de paramètres ou renvois de fonctions que ca se complique : Windev n'autorise que des types simples à être renvoyés par des fonctions Java. (String, int, etc ...)

Autrement dit, dans mon cas, ma fonction écrite en Java ne pourra renvoyer qu'une chaine, pas un tableau binaire.

Je pensais palier aux trous béants dans les possibilités qu'offre Windev avec l'utilisation de Java, mais décidément, il faudrait vraiment qu'ils changent de métier chez PC-Soft, développer des produits à moitié, au prix que ca coûte ...

Pour info, je n'ai pas choisi de travailler sur Windev, c'est comme ca :)

Merci beaucoup à vous deux pour votre aide,
Super communauté ! Bravo !
 

zeb

Modérateur
Merci à toi pour ce retour.
Cette communauté n'est "super" que par l'accumulation des qualités de ces membres dont tu fais partie.
 

KyrO_82

Grand Maître
Une array c'est un type simple, je vois pas comment on peut faire sans :ouch:
Tu peux toujours utiliser un codage texte pour transmettre tes données binaires (base64 par ex), mais ça va augmenter la taille de tes données. Il devient absurde de transformer du texte en binaire (avec la compression) puis de recoder ces données binaire en texte (avec base64).

Tu n'as pas répondu à ma question: As-tu beaucoup de données à compresser? Car si il s'agit juste d'un peu de texte, laisse tomber la compression zip, elle ne t'apportera rien (genre si tu t'amuse à compresser le nom d'utilisateur et le mot de passe de l'utilisateur, tu vas rien y gagner, au contraire)
 
Vous devez vous inscrire ou vous connecter pour répondre ici.
Derniers messages publiés
Statistiques globales
Discussions
730 132
Messages
6 718 000
Membres
1 586 387
Dernier membre
ouistititouille
Partager cette page
Haut