87 votes

Afficher des chaînes unicode dans une application console Windows

Bonjour, j'ai essayé d'envoyer une chaîne unicode à une console avec iostreams et a échoué.

J'ai trouvé ça : Utilisation d'une police unicode dans une application console c++. et ce snippet fonctionne.

SetConsoleOutputCP(CP_UTF8);
wchar_t s[] = L"èéøÞæa";
int bufferSize = WideCharToMultiByte(CP_UTF8, 0, s, -1, NULL, 0, NULL, NULL);
char* m = new char[bufferSize]; 
WideCharToMultiByte(CP_UTF8, 0, s, -1, m, bufferSize, NULL, NULL);
wprintf(L"%S", m);

Cependant, je n'ai pas trouvé de moyen de sortir l'unicode correctement avec iostreams. Avez-vous des suggestions ?

Cela ne fonctionne pas :

SetConsoleOutputCP(CP_UTF8);
utf8_locale = locale(old_locale,new boost::program_options::detail::utf8_codecvt_facet());
wcout.imbue(utf8_locale);
wcout << L"¡Hola!" << endl;

EDIT Je n'ai pas trouvé d'autre solution que d'envelopper ce snippet dans un flux. J'espère que quelqu'un a une meilleure idée.

//Unicode output for a Windows console 
ostream &operator-(ostream &stream, const wchar_t *s) 
{ 
    int bufSize = WideCharToMultiByte(CP_UTF8, 0, s, -1, NULL, 0, NULL, NULL);
    char *buf = new char[bufSize];
    WideCharToMultiByte(CP_UTF8, 0, s, -1, buf, bufSize, NULL, NULL);
    wprintf(L"%S", buf);
    delete[] buf; 
    return stream; 
} 

ostream &operator-(ostream &stream, const wstring &s) 
{ 
    stream - s.c_str();
    return stream; 
}

0 votes

Pourriez-vous préciser en quoi elle est défaillante ? Vous obtenez des caractères tronqués ou erronés, par exemple ? Avez-vous essayé de capturer STDOUT et de vérifier que les bons octets sont envoyés mais ne sont pas affichés ?

1 votes

Il affiche des espaces réservés au lieu de caractères. Je n'ai pas cherché très loin. La seule chose que je peux dire, c'est que pour une raison quelconque, la même chaîne envoyée à wcout ou cout devient folle alors que wprintf l'affiche sans problème.

0 votes

Seulement un peu de Les caractères Unicode peuvent être affichés correctement dans la console Win32. La console ne prend pas en charge les caractères trop compliqués ou ceux qui ont des marques de combinaison qui affectent leur taille. Essayez-le avec WriteConsoleW -- Si ça ne marche pas avec ça, alors c'est impossible.

109voto

DuckMaestro Points 4941

J'ai vérifié une solution ici en utilisant Visual Studio 2010. Via ce Article de MSDN y Article de blog MSDN . L'astuce est un appel obscur à _setmode(..., _O_U16TEXT) .

Solution :

#include <iostream>
#include <io.h>
#include <fcntl.h>

int wmain(int argc, wchar_t* argv[])
{
    _setmode(_fileno(stdout), _O_U16TEXT);
    std::wcout << L"Testing unicode -- English --  -- Español." << std::endl;
}

Capture d'écran :

Unicode in console

4 votes

+1 et supprimé ma réponse. C'est la méthode que nous avons choisie pour Instalog .

9 votes

Il n'affiche toujours pas les caractères japonais dans ma console.

0 votes

Et plus encore : il y a un obscur L avant la chaîne constante. Comment appliquer cela sur des chaînes non constantes ?

3voto

Puppy Points 90818

La locale du wcout doit être différente de celle du CRT. Voici comment le corriger :

int _tmain(int argc, _TCHAR* argv[])
{
    char* locale = setlocale(LC_ALL, "English"); // Get the CRT's current locale.
    std::locale lollocale(locale);
    setlocale(LC_ALL, locale); // Restore the CRT.
    std::wcout.imbue(lollocale); // Now set the std::wcout to have the locale that we got from the CRT.
    std::wcout << L"¡Hola!";
    std::cin.get();
    return 0;
}

Je viens de le tester, et il affiche la chaîne de caractères ici tout à fait correctement.

1 votes

Merci pour cette nouvelle idée et cela a fonctionné pour cette chaîne de caractères mais cela échoue pour quelque chose de plus compliqué comme "¡Hola ! ambul :)".

0 votes

Cette chaîne n'a pas fonctionné avec wprintf non plus, elle est apparue comme un blanc total. wcout a obtenu au moins quelques caractères corrects. Pourriez-vous vérifier que wprintf obtient cette chaîne correctement ?

0 votes

Oui, si vous sélectionnez les polices correctes pour la console et que vous la démarrez avec cmd.exe, cela fonctionne.

1voto

Henrik Haftmann Points 77

SetConsoleCP() et chcp n'est pas le même !

Prenez cet extrait de programme :

SetConsoleCP(65001)  // 65001 = UTF-8
static const char s[]="tränenüberströmt™\n";
DWORD slen=lstrlen(s);
WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE),s,slen,&slen,NULL);

Le code source doit être enregistré en UTF-8. sin BOM (Byte Order Mark ; Signature). Ensuite, le compilateur de Microsoft cl.exe prend les chaînes UTF-8 telles quelles.
Si ce code est enregistré avec BOM, cl.exe transcende la chaîne en ANSI (i.e. CP1252), qui ne correspond pas à CP65001 (= UTF-8).

Changez la police d'affichage en Console Lucidia sinon, la sortie UTF-8 ne fonctionnera pas du tout.

  • Type : chcp
  • Réponse : 850
  • Type : test.exe
  • Réponse : trñnenberstrÂmtÔäó
  • Type : chcp
  • Réponse : 65001 - Ce paramètre a été modifié par SetConsoleCP() mais sans effet utile.
  • Type : chcp 65001
  • Type : test.exe
  • Réponse : tränenüberströmt™ - Tout va bien maintenant.

Testé avec : Windows XP SP3 allemand

1 votes

Vous pouvez utiliser des constantes de caractères comme \x45 pour que la chaîne fonctionne quel que soit l'encodage de la source

2 votes

-1 mauvais conseil pour tromper le compilateur, ce qui entraîne une compilation incorrecte des littéraux larges.

0 votes

Vous voulez vraiment utiliser des échappatoires afin de ne pas dépendre de la façon dont les caractères non-ASCII dans la source sont enregistrés par l'éditeur et interprétés par le compilateur. Par exemple, la chaîne UTF-8 de la réponse peut être écrite de manière portable comme suit "tr\xc3\xa4nen\xc3\xbcberstr\xc3\xb6mt\xe2\x84\xa2" .

0voto

call me Steve Points 719

Je ne pense pas qu'il y ait une réponse facile. en regardant Pages de code de la console y Fonction SetConsoleCP il semble que vous deviez configurer une page de code appropriée pour le jeu de caractères que vous allez produire.

0voto

newtover Points 12301

Récemment, j'ai voulu faire du streaming unicode de Python vers la console Windows et voici le minimum que j'ai dû faire :

  • Vous devez définir la police de la console comme étant celle qui couvre les symboles unicode. Il n'y a pas un grand choix : Propriétés de la console > Police > Lucida Console
  • Vous devez changer la page de code de la console actuelle : run chcp 65001 dans la console ou utiliser la méthode correspondante dans le code C++.
  • écrire sur la console en utilisant WriteConsoleW

Consultez un article intéressant sur java unicode sur la console Windows

De plus, en Python, vous ne pouvez pas écrire dans le sys.stdout par défaut dans ce cas, vous devrez le remplacer par quelque chose utilisant os.write(1, binarystring) ou un appel direct à un wrapper autour de WriteConsoleW. Il semble qu'en C++, vous devrez faire de même.

4 votes

Vous devez définir la police, cette partie est correcte et c'est une mauvaise conception de Windows de ne pas utiliser par défaut une police qui fonctionne pour une gamme décente de caractères Unicode. Cependant, la partie suivante de votre réponse est fausse. Vous n'avez PAS besoin de définir la page de code sur UTF-8/65001 ET d'appeler WriteConsoleW. Vous devez faire l'un OU l'autre. Définissez la page de code si vous appelez WriteConsoleA et si vous transmettez des chaînes de caractères 8 bits, y compris UTF-8, MAIS si vous appelez WriteConsoleW, vous ignorez complètement les pages de code et vous avez besoin d'UTF-16 (caractères larges). Cependant, d'après mon expérience, le réglage de la console sur 65001 est assez bogué.

0 votes

@hippietrail : Je ne suis pas sûr de l'écriture avec WriteConsoleW sans changer le codepage à 65001, mais le réglage à 65001 seulement n'est malheureusement pas suffisant. Au moins pour la sortie unicode des scripts Python.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X