IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

Conversion 255 premiers caractères Unicode vers UTF-8


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Juillet 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2012
    Messages : 7
    Par défaut Conversion 255 premiers caractères Unicode vers UTF-8
    Bonjour à tous,

    Je débute des cours en Java et j'ai un exercice qui me prends bien la tête... Je dois convertir les 255 premiers caractères Unicode vers UTF-8. De ce que je comprends Java fait de base de l'Unicode dans cette forme: (char)car = '\uxxxx' ou String str = "\\uxxxx".

    Donc dans mon idée je fais un for (int i = 0; i<255; i++), j'incrémente un String et je le traduit en UTF-8 via la méthode "getBytes("UTF-8")" et de la possibilité de forcer le format lors de la création de l'objet String.

    Donc j'ai pondu ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    String symbol = "\\u0000";
    for (int i = 0; i<255; i++){
     
    String hex = Integer.toHexString(i);
     
    			  if(i< 9){
    				  symbol = "\\u000"+hex;
    			  }else if (i >10 && i <100){
    				  symbol = "\\u00"+hex;
    			  }else{
    				  symbol = "\\u0"+hex; 
    			  }
     
    char carResult = (char) Integer.parseInt(symbol.substring(2), 16 );
    System.out.println("carResult: "+ carResult);
     
    String string2convert =  Character.toString((char) carResult);
     
    byte[] convertUnicodeBytes = string2convert.getBytes();
    byte[] convertUTF8Bytes2 = string2convert.getBytes("UTF-8");
     
    String stringUTF8= new String(convertUTF8Bytes2, "UTF-8");
    String stringUnicode = new String(convertUnicodeBytes, "UTF-8");
     System.out.println("stringUTF8: "+ stringUTF8 +" stringUnicode: "+ stringUnicode);
    }
    Outre le problème de l'addition des hexadécimaux qui ne fonctionne pas (des idées ?) est-ce la bonne manière de faire ? Et existe-t-il un moyen (ou pas) de faire ça en ayant juste des char et pas des String (avec du pur algo) ?

    Merci de m'avoir lu :-), toute aide est la bienvenue (même en pseudo code... surtout si mon prof passe par là :-))

  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Hello,

    Java fait de base de l'Unicode, tout court. Pas besoin de chercher une notation.
    La notation \uXXXX ne peut pas t'aider, parce qu'elle ne concerne que les littéraux String et char. Uniquement ce que tu mets entre " et " ou bien entre ' et '. On ne peut pas "construire" cette notation à l'intérieur d'un programme, on peut seulement l'écrire dans le code source. Et c'est à ça qu'elle sert, il serait inutile et inadapté qu'elle fasse autre chose.


    Quand je dis que Java fait de l'Unicode tout court, je veux dire que les char Java, c'est de l'Unicode et pas autre chose. Pas besoin de chercher plus.

    Prenons le code Unicode décimal 65, qui correspond à la lettre A. Et faisons ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char ch = 65;
    System.out.println(ch);
    Ça affiche A. C'est pas plus compliqué que ça. Pour avoir dans un char un caractère Unicode précis, tu lui assignes sa valeur. Parce qu'un char c'est de l'Unicode.


    Pour ce qui est de convertir en UTF-8 ensuite, tu vas devoir forcément passer par des String. Un char ne suffit pas, il faut en faire une String. L'encodage de charset se fait sur l'ensemble d'un texte, par sur ses caractères séparés.

    Une question que je me pose, c'est : que vas-tu en faire après avoir converti ces caractères en UTF-8 ? Des caractères encodés, ce sont des octets. Les octets ce n'est pas quelque chose d'intéressant à montrer, normalement on montre plutôt du texte. Les octets on les met plutôt dans un fichier ou dans une communication réseau. Alors que vas-tu en faire ?
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Juillet 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2012
    Messages : 7
    Par défaut
    Salut Thelvin, et merci pour ce retour :-) tu es la lumière au bout du tunnel...

    Je comprends mieux comment faire maintenant, je vais partir sur l'incrémentation des char de 0 à 255 tout simplement et repartir sur un String en forçant le format à UTF-8 pour l'afficher.

    Voilà le résultat:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    import java.io.UnsupportedEncodingException;
    import java.nio.charset.StandardCharsets;
     
    //The character encoding describes how to map a byte array (byte[]) to a char array (char[]), and vice versa
    public class UnicodeVersUtf8 {
     
    	public static void transform(){
     
    		try {
    			for (int i =0 ; i<255; i++){
     
    				char ch = (char) i;
    				byte[] bytesDeChar = Character.toString(ch).getBytes(StandardCharsets.UTF_8);
    				String stringUTF8 = new String(bytesDeChar, "UTF-8");
    				System.out.println("UTF8: "+stringUTF8+" == char: "+ch);
    			}
     
    		} catch (UnsupportedEncodingException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		transform();
    	}
     
    }
    Pour ce qui est de ce que je veux en faire, ben l'afficher ? J'imaginais (à tort) qu'il y aurait des disparités entre un char unicode (ex char(65)=A) et sa représentation en String UTF-8 mais peux être que le but de l'exercice est de nous faire comprendre que jusqu'à 255 il y a pas de différence...

    Bref, c'est le début des cours et on étudie les primitives, je pense que le but est de nous faire comprendre que selon la primitive (et du charset !!) ce n'est pas codé sur le même nombre de bits sans plus mais cette réponse me paraît presque trop simple... Ou alors il faut comparer les tableau de bytes pour déterminer une différence, ce serait plus intéressant au niveau de la démonstration non (EDIT: ils sont similaires...) ? Donc je sais pas trop quelle est le but de cet exercice...

    Sinon petite question: pourquoi je suis obligé de faire un cast sur l'int pour la création du char (pour un erreur si char > 65535)?

    Mais merci encore pour ton retour ! Je sens que tu es un utilisateur Java éclairé ;-) toutes indication supplémentaire est la bienvenue !!

  4. #4
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Citation Envoyé par exaju Voir le message
    repartir sur un String en forçant le format à UTF-8 pour l'afficher.
    Ce que tu dis là ne veux rien dire. Pour 'afficher', on utilise l'encodage de la console, pas autre chose. Ce que fait par défaut System.out.printXXX
    Une String n'a pas d'encodage donc on ne peux donc pas "forcer" un encodage. La seule chose qui a un encodage c'est du binaire, un fichier donc. Parce que un "encodage", c'est une règle pour transformer des byte en du texte et vice versa.

    Ce code si est complètement neutre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    				byte[] bytesDeChar = Character.toString(ch).getBytes(StandardCharsets.UTF_8);
    				String stringUTF8 = new String(bytesDeChar, "UTF-8");
    car tu transforme en byte[] via utf-8 puis tu retransforme en String via utf-8. Tu as donc exactement la même string qu'au départ.
    Ton code est donc strictement le même que

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    				char ch = (char) i;
    				System.out.println("UTF8: "+ch+" == char: "+ch);
    mais en plus compliqué à lire et à exécuter :/ En tant que débutant, tu devrais tout simplement oublie que String a des constructeurs qui prennent des byte[], ceux-ci ne servent que dans de très très rares cas. Si on te demande de les représenter en UTF 8 pour ton exercice, ça veux surement simplement dire qu'on te demande de les écrire dans un fichier texte en utilisant l'encodage utf8, donc en ouvrant un writer avec cet encodage. Sans avoir l'énoncé, difficile de savoir.
    Citation Envoyé par exaju Voir le message
    Sinon petite question: pourquoi je suis obligé de faire un cast sur l'int pour la création du char (pour un erreur si char > 65535)?
    Que veux tu dire? Un char ne peut pas aller au delà de 65535, puisque les char en java font 16bits

  5. #5
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Juillet 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2012
    Messages : 7
    Par défaut
    Ok. ça avance un peu (du côté de la compréhension) mais pas de l'exercice... Pour info voici l'intitulé exacte de la question: " coder en UTF-8 les 256 premières valeur du code UC16 " ni plus, ni moins. J'en ai déduit UC16=Unicode sur 16 bits et qu'il fallait être indépendant pour la résolution de cet exercice mais peux être que je me trompe ? Donc pas plus d'indications...

    Je vais essayer de comprendre le fond de ta démonstration, j'ai compris que tant que j'affiche des String en console je verrais pas de différence.

    Donc pour démontrer une différence entre les encodages (table de correspondance byte <>caractère différente) je peux les transformer en binaire et les comparer non ? Ou utiliser la classe Writer() pour pousser le tout dans un fichier ?

    Le truc c'est que dans mon code les bytes en UTF-8 ou en Unicode sont similaires...

    Mais tu me dit aussi " L'encodage de charset se fait sur l'ensemble d'un texte, par sur ses caractères séparés" donc avec l'intitulé de l'exercice qui ne parle que des 255 premiers caractères il n'y aura aucune démonstration de différence non ?

    En tout cas merci encore de ta patience... J'avoue que je suis comme une poule qui à trouvé un couteau... ça fait mal parfois :-)

  6. #6
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Citation Envoyé par exaju Voir le message
    Pour info voici l'intitulé exacte de la question: " coder en UTF-8 les 256 premières valeur du code UC16 " ni plus, ni moins. J'en ai déduit UC16=Unicode sur 16 bits et qu'il fallait être indépendant pour la résolution de cet exercice mais peux être que je me trompe ? Donc pas plus d'indications...
    Donc faut voir ton cours / prof pour savoir ce qu'il appelle uc16. Car le seul uc16 que je trouve sur internet, c'est ça:
    Nom : evolution-uc-16.jpg
Affichages : 1629
Taille : 60,3 Ko

  7. #7
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Merci tchize_ pour les précisions concernant "l'affichage d'un encodage".

    Citation Envoyé par exaju Voir le message
    Sinon petite question: pourquoi je suis obligé de faire un cast sur l'int pour la création du char (pour un erreur si char > 65535)?
    D'abord parce qu'un int peut être négatif et un char, non. Du coup en essayant d'assigner un int à un char il y a risque d'erreur, et le compilateur te le fait savoir.
    Si tu fais un cast, tu assumes la compréhension de ce risque d'erreur, et considère probablement que tu as pris des mesures adéquates pour que ce ne soit pas un problème.
    Ici, ta variable i ne prend des valeurs que de 0 à 255, aucune négative, donc tu as bien pris les mesures qui conviennent. Mais c'est toi qui le sais, pas le compilateur. Le cast est donc nécessaire.

    Tu aurais pu faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for(char ch = 0; ch < 256; ch++) {
     
    }
    Et le cast aurait été inutile.


    Ensuite, et même chose, un int peut avoir des valeurs jusqu'à 2.147.483.647 et ce n'est évidemment pas le cas d'un char, d'où risque d'erreur.


    Enfin, reste le cas compliqué des valeurs entre U+FFFF et U+10FFFF. C'est à dire de 65.535 à 1.114.111
    J'ai un peu simplifié en disant que les char, c'est de l'Unicode. C'est vrai tant qu'on reste entre U+0000 et U+FFFF, et donc bien sûr pour les 255 premiers. Mais au-delà, c'est plus compliqué.
    Les char Java tiennent sur deux octets, ils ne peuvent donc représenter les caractères que de U+0000 à U+FFFF. Au-delà, ça ne rentre pas.
    Java gère quand même les caractères qui vont au-delà, mais il faut alors deux char consécutifs, un seul ne suffit pas. Le mécanisme est le même qu'en UTF-16.

    Et donc, si tu essaies de rentrer dans un char une valeur supérieure à 65.535, ça ne rentre pas. Par exemple, dans le cas de U+12345, ça ne rentre pas, et le cast va tronquer cette valeur en enlevant le début et en ne gardant que U+2345. D'où résultat inattendu.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  8. #8
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Juillet 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2012
    Messages : 7
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Merci tchize_ pour les précisions concernant "l'affichage d'un encodage".Enfin, reste le cas compliqué des valeurs entre U+FFFF et U+10FFFF. C'est à dire de 65.535 à 1.114.111J'ai un peu simplifié en disant que les char, c'est de l'Unicode. C'est vrai tant qu'on reste entre U+0000 et U+FFFF, et donc bien sûr pour les 255 premiers. Mais au-delà, c'est plus compliqué.Les char Java tiennent sur deux octets, ils ne peuvent donc représenter les caractères que de U+0000 à U+FFFF. Au-delà, ça ne rentre pas.Java gère quand même les caractères qui vont au-delà, mais il faut alors deux char consécutifs, un seul ne suffit pas. Le mécanisme est le même qu'en UTF-16.
    Merci pour l'explication c'est tout de suite plus clair (le cast vers une primitive/objet codé sur un nombre de bits inférieur = perte) et je vais, avant de voir comment ça peux être sérialisé (c'est le bon terme ?) en plusieurs char si le char est > 65535 (2^16), essayer d'assimiler la base :-)

  9. #9
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Juillet 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2012
    Messages : 7
    Par défaut
    Salut à toi tchize_ j'ai oublié toute politesse car je n'avais pas vu que c'était une réponse d'une autre personne... et donc merci pour ton explication et d'avoir pris un peu de ton temps pour me répondre

    Sinon je continue ma quête du graal de l'encodage

    Je viens de lire la fiche Wikipedia sur UTF8: https://fr.wikipedia.org/wiki/UTF-8 et un exemple de conversion de Oracle: https://docs.oracle.com/javase/tutor...xt/stream.html et je suis partit sur cette démonstration avec un fichier écrit en UTF-8 puis lu et affiché dans une fenêtre...

    Mais le rendu est identique, et si je comprends bien c'est normal, car UTF-8 est codé sur 8 bits (1 octets) mais est "variable" et peux être encodé jusqu'a 32 bits (4 octets) si besoin, donc tous les caractères unicode (sauf les demi-codets kesako ?) sont compatibles.

    Mais si je comprends bien UTF-8 est un sous ensemble d'Unicode et donc tout caractère UTF-8 est valide en Unicode, donc il ne peux y avoir de différence ? ça avance mais je sens que je ne saisi pas encore tout...

Discussions similaires

  1. Réponses: 0
    Dernier message: 24/06/2011, 17h54
  2. Conversion ISO-8859-1 vers UTF-8 dans Eclipse
    Par Jerhom dans le forum Eclipse
    Réponses: 2
    Dernier message: 03/06/2008, 17h35
  3. Réponses: 1
    Dernier message: 05/12/2006, 16h54
  4. Conversion de caractère mssql vers mysql
    Par nicoaix dans le forum SQL Procédural
    Réponses: 1
    Dernier message: 12/10/2006, 10h21
  5. conversion iso-8859-1 vers utf-8
    Par gorgonite dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 20/08/2006, 12h49

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo