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

SL & STL C++ Discussion :

Lecture d'un fichier UTF-16 Little Endian sous MSVC et MinGW/g++


Sujet :

SL & STL C++

  1. #1
    Membre régulier
    Homme Profil pro
    Ingénieur validation
    Inscrit en
    Août 2018
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Côtes d'Armor (Bretagne)

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

    Informations forums :
    Inscription : Août 2018
    Messages : 37
    Points : 123
    Points
    123
    Par défaut Lecture d'un fichier UTF-16 Little Endian sous MSVC et MinGW/g++
    Bonjour

    Le code suivant ouvre un flux sur un fichier écrit en UCS-2 / UTF-16LE avec un BOM.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    // Lecture UTF16-LE / UCS-2
    	wifstream UTFStream("MonFichier.s");
    	wchar_t buffer[16];
    	wstring headerString;
     
    	UTFStream.read(buffer, 2); // Lecture du BOM
    	UTFStream.imbue(locale(UTFStream.getloc(), new codecvt_utf16<wchar_t, 0xffff, little_endian>()));
    	UTFStream.read(buffer, 16);
    	getline(UTFStream, headerString);
     
    	wcout.imbue(locale(UTFStream.getloc(), new codecvt_utf8<wchar_t, 0xffff, little_endian>()));
    	wcout << buffer << endl;
    	wcout << headerString << endl;
    Sous Visual C++, le buffer de wchar_t ou la wstring sont correctement lus et affichés.

    Par contre MinGW et g++ lit le buffer comme s'il s'agissait d'un tableau de char, avec un caractère sur deux égal à 0x00.
    J'ai lu que gcc/g++ a supporté tardivement les jeux de caractères UTF16 mais j'ai la version 6.3.0 qui devrait être à jour.

    Si je ne lis pas le BOM avant d'appliquer la locale par imbue, la fonction read ne lit rien du tout sur g++ alors que Visual C++ alimente le buffer avec buffer[0] = BOM.

    La modification de la locale d'un flux de fichier et les conversions Unicode sont-elles spécifiées dans la norme ou est-ce sujet à l'implémentation de chaque compilateur et donc non portable?

    Merci

  2. #2
    Membre régulier
    Homme Profil pro
    Ingénieur validation
    Inscrit en
    Août 2018
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Côtes d'Armor (Bretagne)

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

    Informations forums :
    Inscription : Août 2018
    Messages : 37
    Points : 123
    Points
    123
    Par défaut
    Bonjour

    J'ai eu l'occasion de faire un test sommaire avec GCC sur Linux. Ça ne fonctionne pas encore comme Visual C++ (problème avec un fichier qui possède un BOM) mais j'arrive bien à lire des caractères larges, conformément à ma facette.
    Il semble donc que mon problème provienne de l'implémentation de la bibliothèque standard fournie avec MinGW.

    A noter que le GCC utilisé sous Fedora était une version 7.1.1. MinGW-get m'indique que la version de mingw32-libstdc++ sur leur repository est bloquée à la 6.3.0-1.
    Y a-t il un moyen de tester une version plus récente?

  3. #3
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Utilises-tu MinGW (http://www.mingw.org/) ou Mingw-64 (https://sourceforge.net/projects/mingw-w64/) ? Le 2e est normalement plus à jour, tu devrais avoir du gcc 7 au minimum.

  4. #4
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    As-tu tenté d'ouvrir le fichier en mode binaire ?

  5. #5
    Membre régulier
    Homme Profil pro
    Ingénieur validation
    Inscrit en
    Août 2018
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Côtes d'Armor (Bretagne)

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

    Informations forums :
    Inscription : Août 2018
    Messages : 37
    Points : 123
    Points
    123
    Par défaut
    Bonjour

    Merci pour ces réponses.

    Ouvrir en mode Binaire n'apporte rien.
    J'ai même tenté ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    wifstream UTFStream("test_utf16.txt", ios::binary);
    wchar_t w;
    UTFStream.read(reinterpret_cast<wchar_t*>(&w), sizeof(wchar_t));
    Passer de MinGW à MinGW-w64 fonctionne en revanche. Je l'ai essayé en mode i686 avec GCC v8.1.0.

    Par contre, par rapport au code du premier message, j'ai dû faire quelques modifications.
    C'est plutôt déconcertant, mais wcout n'accepte pas de caractères larges par défaut.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    wcout << L"abc€" << endl;
    provoque l'armement du failbit et du badbit de la sortie standard, sur MinGW-w64 comme sur Visual C++

    Je n'ai pas trouvé de solution portable.
    On peut écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #include <fcntl.h>
    #include <windows.h>
     
    _setmode(_fileno(stdout), _O_U16TEXT);
    Il est alors possible d'utiliser wcout sous Visual C++.
    Par contre, avec MinGW-w64, on ne peut utiliser que la fonction C wprintf.

    La solution qui fonctionne avec les deux compilateurs : utiliser l'API Windows.
    Ce qui donne :
    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
    // Lecture UTF16-LE / UCS-2
    wifstream UTFStream("test_utf16.txt");
    wchar_t buffer[16];
    wstring headerString;
     
    UTFStream.read(buffer, 2); // Lecture du BOM
    UTFStream.imbue(locale(UTFStream.getloc(), new codecvt_utf16<wchar_t, 0xffff, little_endian>()));
    UTFStream.read(buffer, 15);
    buffer[15]=0;
    getline(UTFStream, headerString);
     
    WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), buffer, wcslen(buffer), NULL, NULL);
    wcout << endl;
    WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), headerString.c_str(), headerString.size(), NULL, NULL);
    wcout << endl;

Discussions similaires

  1. Lecture d'un fichier XML par PL/SQL sous oracle10g
    Par nejib salem dans le forum PL/SQL
    Réponses: 2
    Dernier message: 17/05/2011, 13h35
  2. Lecture/écriture de fichiers UTF 16 LE
    Par Pill_S dans le forum Delphi
    Réponses: 8
    Dernier message: 19/12/2006, 18h08
  3. Lecture d'un fichier texte en UTF-8
    Par EL0807 dans le forum Access
    Réponses: 2
    Dernier message: 07/08/2006, 22h54
  4. [ANT] Pb lecture fichier UTF-8
    Par tnodev dans le forum ANT
    Réponses: 1
    Dernier message: 23/04/2006, 10h52
  5. Lecture de fichier utf-8
    Par cronos6 dans le forum Général Python
    Réponses: 10
    Dernier message: 07/04/2006, 12h00

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