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

API standards et tierces Java Discussion :

Creer un fichier en UTF-8


Sujet :

API standards et tierces Java

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 99
    Par défaut Creer un fichier en UTF-8
    Bonjour j'ai un problème d'écriture dans un fichier en UTF-8. En effet, mon programme est sensé créer un fichier en UTF-8 or dans notepad++, le menu "encoding" ne montre aucun format.
    Mon programme lit bien un fichier source en encoding UTF-8 (comme spécifié par mon notepad++), il lit le contenu de ce fichier dans une string et doit le recopier dans un autre fichier préalablement crée en uTF-8 aussi.
    Mais rien a faire, le contenu du fichier cible est bizarre (je parle des character encodés comme \uFFFD):


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    num_compte = 3 06 3 005 386 056\r\n\r\n
    num_facture = 13 418 979 009\r\n\r\n
    montant_total_ttc = Total TTC 181,91 \uFFFD\r\nA r\uFFFDgler avant le 01/03/2010
    num_client = 1 0009571 52\r\n\r\n




    Mon code :
    Code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
       1. System.setProperty( "file.encoding", "UTF-8" );
       2. PropertiesConfiguration lProps = new PropertiesConfiguration();
       3.  List<String> lOCRContentList = new ArrayList<String>();
       4.  Map<String, String> lPropsMap = new HashMap<String, String>();
       5. ...
       6. String lOCRContentStr = FileUtils.readFileToString( new File(
       7.     lOutputTextFullPathFilename ), "UTF-8" );
       8.   lPropsMap.put( lName, lOCRContentStr );
       9. ...
      10. Writer lPropsFile = new BufferedWriter( new OutputStreamWriter(
      11.    new FileOutputStream( pOutputPropsFullPathFilename ),
      12.    Charset.forName( "UTF-8" ) ) );
      13.  lProps.setHeader( "my interesting comment" );
      14.  lProps.save( lPropsFile );



    Que proposez-vous comme code ?

  2. #2
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 99
    Par défaut
    Tiens je viens d'essaier un autre truc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    PropertiesConfiguration lProps = new PropertiesConfiguration();
    ...
    lProps.save( new FileOutputStream( pOutputPropsFullPathFilename ),
    				"UTF-8" );
    Le fichier de nom absolue pOutputPropsFullPathFilename crée est en ASCII selon notepad++ et même selon linux ubuntu :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    alfresco33g@alfrescodemo:~$ file edf-300dpi-bw.properties
    edf-300dpi-bw.properties: ASCII text, with CRLF line terminators
    Décidément, impossible de créer un fichier au format UTF-8

  3. #3
    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
    le fichier est bien au format utf-8. Si ce sont le \r qui t'ennuie, il faut bien les échapper d'une manière ou d'une autre puisque, dans un fichier properties, les retour à la ligne on une signification particulière. De même, comme indiqué dans la javadoc, PropertiesConfiguration fait un echappement de tout caractère qui ne sois pas latin1.

    Quand à l'ascii, par définition, c'est aussi de l'utf-8 puisque les 127 caractère de base de l'ascii sont mappé avec les même valeur en utf-8.

  4. #4
    Membre éprouvé
    Avatar de _skip
    Homme Profil pro
    Développeur d'applications
    Inscrit en
    Novembre 2005
    Messages
    2 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur d'applications
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 898
    Par défaut
    Je trouve que trifouiller les propriétés système est super moche pour faire ça. Pourquoi ne pas créer un writer utf-8 à la place?

    Perso j'ai cette fonction dans ma boîte à outil pour ce faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    /**
         * Creates and returns a buffered writer for writing UTF-8 encoded files.
         * The caller is responsible for closing the writer.
         *
         * @param fileToWrite The file name to open / create.
         * @param append Setting this param to false overwrites the file.
         * @return A buffered writer.
         * @throws IOException In case of IO errors.
         */
        public static BufferedWriter createBufferedWriterUTF8(String fileToWrite, boolean append) throws IOException
        {
            return new BufferedWriter( new OutputStreamWriter( new FileOutputStream(fileToWrite, append), CharEncoding.UTF_8) );
        }

  5. #5
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 99
    Par défaut
    Merci pour les explications.
    En fait, je vais poser mon problème plus généralement car je galère trop là .

    En entrée, j'ai un fichier de type texte (présent sur le disque) avec le contenu suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Total TTC 181,91 €
    A régler avant le 01/03/2010
    On remarque que ce contenu est parfait sur le symbole € et les accents. De plus il est au format UTF-8 d'après mon notepad++ et la commande 'file' de ubuntu.

    Très concrètement je cherche à :

    1) Lire le contenu de ce fichier
    2) Crée un fichier xxx.properties au format UTF-8 (tout comme le fichier d'entrée).
    3) Ecrire dans le fichier xxx.properties le même contenu que le fichier d'entrée avec des choses en plus (notamment la clé de la valeur).

    Et ben pour avoir un fichier xxx.properties en sortie "identique" au fichier d'entrée, j'ai du mal

  6. #6
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 99
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    le fichier est bien au format utf-8. Si ce sont le \r qui t'ennuie, il faut bien les échapper d'une manière ou d'une autre puisque, dans un fichier properties, les retour à la ligne on une signification particulière. De même, comme indiqué dans la javadoc, PropertiesConfiguration fait un echappement de tout caractère qui ne sois pas latin1.

    Quand à l'ascii, par définition, c'est aussi de l'utf-8 puisque les 127 caractère de base de l'ascii sont mappé avec les même valeur en utf-8.
    C'est donc pour ça que mon symbole euro est tout bizarre...moi je veux un vrai caractère lisible de préférence...comment se fait-il que mon editeur de texte ne converti pas ce symbole au format unicode en caractère lisible ?

  7. #7
    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
    tu ne pourra pas avec les classes de type propertiesConfiguraiton, puisqu'elles obéissent à des règle particulière, documentées dans la javadoc, et qui, semble-t-il, te posent problème. Dans ton cas le mieux est de le faire à la main:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    String[] lignes = ....
    String[] cles = ...
    Writer w = ......;
    int index = 0;
    for (String ligne: lignes){
      writer.write(cles[i++]);
      writer.write(" = ");
      writer.write(ligne);
      writer.write("\n");
    }

  8. #8
    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 zomurn Voir le message
    C'est donc pour ça que mon symbole euro est tout bizarre...moi je veux un vrai caractère lisible de préférence...comment se fait-il que mon editeur de texte ne converti pas ce symbole au format unicode en caractère lisible ?
    parce que cet échappement est spécifique au format des fichier properties et ce n'est pas l'affaire de ton éditeur.

  9. #9
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 99
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    parce que cet échappement est spécifique au format des fichier properties et ce n'est pas l'affaire de ton éditeur.
    Oulala, ça m'embrouille tout ça. Tu veux dire que dans un fichier .properties, les symboles d'encodage d'un jeu de caractère quelconque est différent ? (dans ce cas pas la peine de consulter une table de conversion).
    Je croyais qu'un fichier .properties était un fichier .txt avec un contenu respectant des règles de syntaxe....pas d'encodage.

    En fait je voulais utiliser PropertiesConfiguration pour éviter de faire le bout de code que tu as écris (programmation bas niveau). Mais je crois que je vais rayer cette classe....à moins que mon programme qui lira ce fichier .properties généré le lira comme il faut (qu'il comprenne le symbole euros, etc.), c'est sûr ça ?

  10. #10
    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 zomurn Voir le message
    Oulala, ça m'embrouille tout ça.
    Ne confond pas l'encodage et l'échappement. Exemple simple. Soit la requête SQL suivante stocké dans un fichier utf-8:



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    insert into maTable value("Bonjour monsieur \"tartempion\" et bonne journée");
    \" est un échappement (spécifique au language SQL en l'occurence)
    tous les caractère seront stocké sur base de l'encodage choisi (et donc "é" prendra 2 bytes).

    En l'occurence, le format "properties" exige (ce sont ses règles de syntaxe) que tout ce qui n'est pas latin1 soit échappé sous la forme \uxxxx avec xxxx le code unicode du caractère, et ce indépendament de l'encodage du fichier. De même tout clé ou valeur contenant des tabulation, retour chariot retour à la ligne sont échappée en utilisant \n\r\t.

  11. #11
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 585
    Par défaut
    Il y a un truc que personne n'a vu, là : en aucune circonstance, le symbole euro ne peut s'échapper en \uFFFD. D'autant plus que l'accent a été échappé pareil.

    Comment cela est-il arrivé ? À mon avis, c'est au niveau du CharsetDecoder : il lit le fichier, et quand il tombe sur le symbole euro ou le é, il dit que c'est autre chose à la place, à savoir le caractère U+FFFD.

    Bon, et ça, ça arrive comment ? À ma connaissance, ça arrive avec les fichiers mal encodés en UTF-8. Je m'explique : avec les règles d'UTF-8, on peut penser qu'un caractère peut être représenté de différentes façons : soit en 1, soit en 2, soit en 3, soit en 4, soit en 5, soit en 6 octets.
    Pour ces raisons, UTF-8 impose une règle supplémentaire : il faut utiliser la représentation la plus courte possible. Un caractère ASCII en 1 octet, le é en 2 octets, le € en 3 octets.

    Certains programmes, notamment notepad++ et file, tolèrent que cette dernière règle ne soit pas respectée. Mais les versions récentes de Java ne le tolèrent pas : les spécifications d'UTF-8 sont claires, un non-respect est un caractère invalide.

    J'ignore si des charsetDecoder plus tolérants, ou d'autres formes de solutions, existent pour réparer ce genre de fichiers.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  12. #12
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 99
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Ne confond pas l'encodage et l'échappement. Exemple simple. Soit la requête SQL suivante stocké dans un fichier utf-8:



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    insert into maTable value("Bonjour monsieur \"tartempion\" et bonne journée");
    \" est un échappement (spécifique au language SQL en l'occurence)
    tous les caractère seront stocké sur base de l'encodage choisi (et donc "é" prendra 2 bytes).

    En l'occurence, le format "properties" exige (ce sont ses règles de syntaxe) que tout ce qui n'est pas latin1 soit échappé sous la forme \uxxxx avec xxxx le code unicode du caractère, et ce indépendament de l'encodage du fichier. De même tout clé ou valeur contenant des tabulation, retour chariot retour à la ligne sont échappée en utilisant \n\r\t.
    Bon ben je ne peux que te remercier de ces renseignements sur ces spécifications des fichiers .properties que j'ignoraient totalement.
    En résumé, je dois donc créer mon fichier en utilisant une API I/O et pas une API de fichiers .properties si je veux voir mon caractère...

    Merci.

  13. #13
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 585
    Par défaut
    Citation Envoyé par zomurn Voir le message
    En résumé, je dois donc créer mon fichier en utilisant une API I/O et pas une API de fichiers .properties si je veux voir mon caractère...
    Oui. Mais dans ce cas-là, ce ne sera plus un fichier au format .properties, mais un fichier dont tu as, seul, unilatéralement, sans en parler à personne, défini le format. Personne ne saura comment le lire ni l'écrire, à part toi.

    (Et j'invite à lire ma remarque au-dessus, concernant le fait que le € et le é ont été échappés de la même façon, ce qui bien sûr ne peut pas se passer normalement.)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  14. #14
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    Accessoirement les fichiers properties se doivent d'être écrits en ISO 8859-1, comme il est indiqué dans la javadoc de la classe properties:

    The load(Reader) / store(Writer, String) methods load and store properties from and to a character based stream in a simple line-oriented format specified below. The load(InputStream) / store(OutputStream, String) methods work the same way as the load(Reader)/store(Writer, String) pair, except the input/output stream is encoded in ISO 8859-1 character encoding. Characters that cannot be directly represented in this encoding can be written using Unicode escapes ; only a single 'u' character is allowed in an escape sequence. The native2ascii tool can be used to convert property files to and from other character encodings.
    Cette javadoc indique également que si des caractères unicode doivent être intégrés, ils doivent être représentés sous leur forme échappée, à) savoir un \u suivi du code UTF-8 du caractère.

  15. #15
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 99
    Par défaut
    Ne prête pas attention aux caractères unicode, je crois que ce sont plus mes 1ère versions de code qui étaient foireuses.

    voici la dernière version et qui marche (j'ai fait une écriture puis une relecture de mon fichier crée) :

    code :

    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
    PropertiesConfiguration lProps = new PropertiesConfiguration();
    ....
    String lOCRContentStr = FileUtils.readFileToString( new File(
    					lOutputTextFullPathFilename ) );
    			lPropsMap.put( lName, lOCRContentStr );
    ....
     
    String[] lSearchList = { System.getProperty( "line.separator" ), "," };
    		String[] lReplacementList = { "", "\\," };
    		//alimentation du fichier résultat final
    		for (Map.Entry<String, String> lProp : lPropsMap.entrySet())
    		{
    			//on supprime les nouvelles lignes et on escape la virgule
    			lProps.setProperty( lProp.getKey(), StringUtils.replaceEach(
    					lProp.getValue(), lSearchList, lReplacementList ) );
     
    		}
     
    Writer w = new BufferedWriter( new OutputStreamWriter(
    				new FileOutputStream( pOutputPropsFullPathFilename ),
    				CharEncoding.UTF_8 ) );
     
    		lProps.setHeader( "Extracted values from template" );
     
    		lProps.save( w );
    output :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Total TTC 181\,91 \u20ACA r\u00E9gler avant le 01/03/2010
    Si j'enlève la notion "UTF-8' dans le OutputStreamWriter, ça ne change rien , ça marche pareil. En fait, c'est à cause de mes caractères qui rentrent encore dans la table ASCII (qui est le format par défaut pris par le OutputStreamWriter)

    Voili voiloù

  16. #16
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 585
    Par défaut
    Citation Envoyé par sinok Voir le message
    Cette javadoc indique également que si des caractères unicode doivent être intégrés, ils doivent être représentés sous leur forme échappée, à) savoir un \u suivi du code UTF-8 du caractère.
    Leur code point Unicode, en fait. (Et une représentation en surrogates pour les caractères au delà de U+FFFF. Beurk.)

    voici la dernière version et qui marche (j'ai fait une écriture puis une relecture de mon fichier crée) :
    Pour information, la classe Properties s'occupe toute seule de faire les échappements nécessaires, quand on s'en sert.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

Discussions similaires

  1. Creer un fichier encoder en utf-8
    Par erehcab dans le forum Langage
    Réponses: 0
    Dernier message: 02/11/2011, 16h39
  2. [File][UTF-16]comment creer un fichier xml en utf-16?
    Par Invité dans le forum Format d'échange (XML, JSON...)
    Réponses: 1
    Dernier message: 10/01/2006, 15h40
  3. creer un fichier cpl
    Par Louis-Guillaume Morand dans le forum Windows
    Réponses: 5
    Dernier message: 04/03/2004, 19h10
  4. Réponses: 19
    Dernier message: 24/05/2002, 16h36
  5. [langage] comment créer des fichiers ?
    Par Anonymous dans le forum Langage
    Réponses: 3
    Dernier message: 05/05/2002, 16h33

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