Encodage de caractères

Flexx
Encodage de caractères

Bonjour

Dans une application, je reçois une chaine de caractère avec pour entete 0x15 0xC0, visiblement encodé en UTF-8 puisque lorsque j'affiche la valeur décimale j'obtiens 65533 au lieu de 192.

Je cherche donc à convertir cet entete en ISO et je vérifie que j'obtiens bien en décimal 21(0x15) et 192(0xC0).

Le problème, c'est que j'obtiens 63 au lieu de 192 !
L'exemple ci-dessous montre la conversion effectuée.

String stringUTF8 = new String(new byte[] {0x15, (byte)0xC0}, "UTF-8");		
char [] myTabDonneesUTF8 = stringUTF8.toCharArray();
			
System.out.println(myTabDonneesUTF8);
System.out.println("1er caract = " + myTabDonneesUTF8[0] + "   : " + (int)(myTabDonneesUTF8[0]));
System.out.println("2eme caract = " + myTabDonneesUTF8[1] + "   : " + (int)(myTabDonneesUTF8[1]));
 
 
String stringISO = new String (stringUTF8.getBytes(), "ISO-8859-1" );
char [] myTabDonneesISO = stringISO.toCharArray();
 
System.out.println(myTabDonneesISO);
System.out.println("1er caract = " + myTabDonneesISO[0] + "   : " + (int)(myTabDonneesISO[0]));
System.out.println("2eme caract = " + myTabDonneesISO[1] + "   : " + (int)(myTabDonneesISO[1]));

Il doit y avoir un problème de dépassement qqpart (255 - 63 = 192).

Pouvez-vous m'éclairer sur ce sujet ?

Merci d'avance

fredericmazue

Quote:
Dans une application, je reçois une chaine de caractère

Reçois d'où :?: de qui :?: comment :?: Quel OS :?:

Quote:
visiblement encodé en UTF-8

Peut être, peut être pas.
En Java l'encodage par défaut est UTF-16

Va voir les classes java.nio
CharBuffer
CharsetEncoder
CharsetDecoder

Ca t'aidera peut être

Flexx

Merci pour ta réponse

J'ai refais un mini-exemple.
Je crée ma chaine avec CO. Mais lorsque je refais la convertion à partir du caractère, j'obtiens FFFD !

String maChaine = new String(new byte[] {0x15, (byte)0xC0}, "UTF-8");
char [] tabChaine = maChaine.toCharArray();
System.out.println("Valeur hexa : " + Integer.toHexString((int)(tabChaine[1])));

Peux-tu me dire où est la perte de données et comment réaliser correctement la convertion ?

Merci

fredericmazue

Quote:
Peux-tu me dire où est la perte de données et comment réaliser correctement la convertion ?

Non.
Quand j'essaie d'aider quelqu'un je voudrais bien ne pas (ne plus) devoir m'y reprendre à mille fois. Regarde le thread jpcap juste à côté avec emmi, tu verras ce que je veux dire.
Je t'ai demandé:
Quote:
Reçois d'où :?: de qui :?: comment :?: Quel OS :?:

Cela a de l'importance au moins pour moi sinon pour toi. Tu ne daignes pas préciser. Alors je ne me lance pas dans l'aventure cette fois.
Flexx

Soit pas aussi agressif ! Reste Zen :wink:

En fait, j'ai refais un mini-exemple parce que je trouvais que le précédent était un peu trop compliqué et qu'il pouvait susciter beaucoup de questions.

Bon, pour répondre à tes questions, je reçois l'entête de la chaine d'une interface extérieure par réseau via une socket, et l'appli tourne sous Linux.
Par contre, mon mini-exemple a été fait sous Windows.

Donc, pour reprendre cet exemple, lorsque je crée ma chaine UTF-8, je suis obligé de caster le C0 en (byte) sinon le compilateur Java me met une erreur :
new String(new byte[] {0x15, (byte)0xC0}, "UTF-8");

Et en fait, un byte est une valeur entière sur 8 bits signée (complément à 2) donc de -128 à 127 inclus.
La perte doit venir de là.
Mais du coup, je ne sais pas si c'est possible d'avoir une chaine de caractères correspondant aux octets 0x15 0xC0.

Bref, mais te casse pas la tête dessus, je vais trouver.

Merci qd meme

fredericmazue

Quote:
Soit pas aussi agressif ! Reste Zen

Je suis Zen et pas agressif.
Au fait tu sais que les maîtres Zen corrigent souvent leur disciples à grands coups de bâtons ? Tu vois à quoi tu as échappé, alors ne te plains pas :D

Une longue pratique de ce forum m'a appris à ne pas bosser pour rien sur des questions pas claire.. J'ai aussi appris qu'aider quelqu'un qui demande de l'aide est un vrai défi :twisted:
Et justement dans cette question tout reste nébuleux.

Quote:
je reçois l'entête de la chaine d'une interface extérieure par réseau via une socket, et l'appli tourne sous Linux.

Donc selon toutes probabilités et à moins d'informations contraires, la chaîne reçue est en ASCII.
Je parle au niveau de l'échange de données dans le socket.
Si Java traite les octets pour en faire une String, alors c'est de l'UTF-16, c'est à dire l'encodage par défaut et non de l'UTF-8
Donc qu'on se place au niveau du socket ou de la chaîne, pourquoi diable nous dit tu dans la questino initiale que c'est de l'UTF-8 ?

Quote:
lorsque je crée ma chaine UTF-8,

Mais pourquoi diable faire ça, puisque la question au départ est de décoder de UTF-8 vers ISO. Tu veux encoder ou décoder de l'UTF-8 ? Faut savoir....

Comme je disais plus haut, aider quelqu'un malgré lui est un vrai défi, demande une grande patience et de rester zen...
Et aussi d'attendre te voir si la question s'éclaircit ou pas :D

Quote:
Bref, mais te casse pas la tête dessus, je vais trouver.

Je te le souhaite.
Quand à moi je retourne à ma pratique de zazen :)
Niroken

Bonjour,

Après maintes bidouilles et recherches sur l'encodage pour ton cas
j'ai peut être trouvé une solution :

String maChaine = new String(new byte[] {0x15, (byte)(0xC0)}, "UTF-16"); 
char [] tabChaine = maChaine.toCharArray(); 
System.out.println("Valeur hexa : " + Integer.toHexString((int)(tabChaine[0])));

il retourne 15c0.

Avant ca ne pouvait pas fonctionner puisque lorsque tu cast 0xC0 en byte
tu perds en précision puisque 0xC0 vaut 192 et un byte est compris entre
-127 et 128 : grosso modo ton 192 il te le transformait en valeur négative.

Dans le cas de figure ou ca fonctionne, je t'avoue que je ne saurais trop
t'expliquer ce qui s'est passé j'ai surtout procédé par tatonnements.

J'espère que ca pourra t'aider tt de même.
Bonne chance

fredericmazue

Quote:
il retourne 15c0.

Et c'est ça le but poursuivi par Flexx ?
Si oui, pourquoi s'embêter ? Il suffit d'imprimer la représentation hexa de chaque octet. Sans même passer par la constitution d'une chaîne.
Enfin bref, moi je ne comprends pas sa question alors tu as peut être tout bon :)

Quote:

Avant ca ne pouvait pas fonctionner puisque lorsque tu cast 0xC0 en byte
tu perds en précision puisque 0xC0 vaut 192 et un byte est compris entre
-127 et 128 : grosso modo ton 192 il te le transformait en valeur négative.

Je crois qu'il y a confusion. "Avant", c'est à dire avec UTF-8 si je comprends bien, la chaîne contient DEUX caractères codées en unicode UTF-8
Dans ton cas (UTF-16) elle n'en contient qu'un seul.

Pour en revenir à sa question, si 0x15 et 0xC0 sont de l'encodage UTF-8 comme il l'affirme, va falloir qu'il m'explique ce que ça veut dire.
Parce que, si encodage UTF-8, alors 0x15, car inférieur à 0x7F, se traduit directement en ASCII. C'est le code de contrôle NAK dont la présence ici à de quoi surprendre. Quant à C0 qui ne veut rien dire en UTF-8, après cast en byte, ça se traduit ? donc la représentation ASCII totale de sa chaîne, si l'on peut dire, car NAK n'est pas imprimable, est

NAK ?

A moins que ça soit un nouveau code pour la CIA, il y a erreur dans la question.
Ou je n'ai rien compris ce qui est toujours possible :lol:

fredericmazue

Je reviens un instant sur la discussion.

Je me dis que je n'ai pas été assez clair.
Si la chaîne reçue commence par 0x15 et 0XC0, alors elle ne PEUT PAS être de l'UTF-8, tout du moins de l'UTF-8 valide.

Tu as dit:

Quote:
je reçois l'entête de la chaine d'une interface extérieure par réseau via une socket, et l'appli tourne sous Linux.

Déjà un linux qui envoie de l'UTF-8, ça existe certes mais c'est rare.

Donc je renouvelle ma question. Qui envoie cette chaîne? Je veux dire, au delà de Linux quelle application ? Une application connue ?
Une application de quel genre ? Communiquant quels types d'informations ou données ?
Ce sont des renseignements qui pourraient aider à comprendre comment est encodée la chaîne.
Mais si une chose est bien certaine, c'est que ce n'est pas de l'UTF-8

Flexx

Merci pour vos réponses

Le problème a été réglé d'une autre manière.
Il devait y avoir un problème d'encodage ou de cast. J'y reviendrais lorsque j'aurais un peu plus de temps. Dans ce cas, je vous tiendrai au courant.

A+

fredericmazue

Quote:
Le problème a été réglé d'une autre manière.

C'est qu'on aurait aimé savoir ?...

Quote:
Il devait y avoir un problème d'encodage

Ah ça, je ne te le fait pas dire ;)