Question Comment écrire std :: wstring dans un fichier?


j'ai un wstring déclaré comme tel:

// random wstring
std::wstring str = L"abcàdëefŸg€hhhhhhhµa";

Le littéral serait encodé en UTF-8, car mon fichier source l'est.

[EDIT: Selon Mark Ransom, ce n'est pas nécessairement le cas, le compilateur décidera de l'encodage à utiliser - supposons plutôt que je lis cette chaîne à partir d'un fichier encodé, par ex. UTF-8]

Je voudrais beaucoup que cela entre dans une lecture de fichier (lorsque l'éditeur de texte est défini sur le codage correct)

abcàdëefŸg€hhhhhhhµa

mais ofstream n'est pas très coopératif (refuse de prendre wstring paramètres), et wofstream soi-disant besoin de connaître les paramètres régionaux et de codage. Je veux juste sortir cet ensemble d'octets. Comment fait-on normalement cela?

EDIT: il doit s'agir d'une plate-forme croisée, et ne devrait pas compter sur l'encodage étant UTF-8. Je viens juste d'avoir un ensemble d'octets stockés dans un wstring, et que vous voulez les sortir. Il pourrait très bien s'agir d'UTF-16 ou d'ASCII.


17
2017-10-29 16:31


origine


Réponses:


Pourquoi ne pas écrire le fichier en binaire. Il suffit d'utiliser ofstream avec le paramètre std :: ios :: binary. L'éditeur devrait pouvoir l'interpréter alors. N'oubliez pas le drapeau Unicode 0xFEFF au début. Vous pourriez peut-être mieux écrire avec une bibliothèque, essayez l'une de ces méthodes:

http://www.codeproject.com/KB/files/EZUTF.aspx

http://www.gnu.org/software/libiconv/

http://utfcpp.sourceforge.net/


7
2017-10-29 16:57



Pour std::wstring vous avez besoin std::wofstream

std::wofstream f(L"C:\\some file.txt");
f << str;
f.close();

26
2017-08-14 08:11



std::wstring est pour quelque chose comme UTF-16 ou UTF-32, ne pas UTF-8. Pour UTF-8, vous voulez probablement simplement utiliser std::string, et écrivez via std::cout. Juste FWIW, C ++ 0x aura des littéraux Unicode, ce qui devrait aider à clarifier des situations comme celle-ci.


13
2017-10-29 16:39



C ++ permet d'effectuer une conversion de caractères larges en caractères localisés en sortie ou en écriture de fichier. Utilisation facette codecvt à cette fin.

Vous pouvez utiliser le standard std :: codecvt_byname, ou un codecvt_facet non standard la mise en oeuvre.

#include <locale>
using namespace std;
typedef codecvt_facet<wchar_t, char, mbstate_t> Cvt;
locale utf8locale(locale(), new codecvt_byname<wchar_t, char, mbstate_t> ("en_US.UTF-8"));
wcout.imbue(utf8locale);
wcout << L"Hello, wide to multybyte world!" << endl;

Attention, sur certaines plateformes, codecvt_byname ne peut émettre que des conversions pour les environnements locaux installés sur le système. Je recommande donc de rechercher stackoverflow pour "utf8 codecvt "et faire un choix parmi de nombreux référents d'implémentations de codecvt personnalisées listés.

MODIFIER: Comme OP déclare que la chaîne est déjà codée, il lui suffit de supprimer les préfixes L et "w" de chaque jeton de son code.


4
2017-10-29 17:03



Il existe une solution (spécifique à Windows) qui devrait vous convenir ici. Fondamentalement, convertir wstring à la page de code UTF-8 et ensuite utiliser ofstream.

#include < windows.h >

std::string to_utf8(const wchar_t* buffer, int len)
{
        int nChars = ::WideCharToMultiByte(
                CP_UTF8,
                0,
                buffer,
                len,
                NULL,
                0,
                NULL,
                NULL);
        if (nChars == 0) return "";

        string newbuffer;
        newbuffer.resize(nChars) ;
        ::WideCharToMultiByte(
                CP_UTF8,
                0,
                buffer,
                len,
                const_cast< char* >(newbuffer.c_str()),
                nChars,
                NULL,
                NULL); 

        return newbuffer;
}

std::string to_utf8(const std::wstring& str)
{
        return to_utf8(str.c_str(), (int)str.size());
}

int main()
{
        std::ofstream testFile;

        testFile.open("demo.xml", std::ios::out | std::ios::binary); 

        std::wstring text =
                L"< ?xml version=\"1.0\" encoding=\"UTF-8\"? >\n"
                L"< root description=\"this is a naïve example\" >\n< /root >";

        std::string outtext = to_utf8(text);

        testFile << outtext;

        testFile.close();

        return 0;
}

2
2017-10-29 16:39



Notez que les flux étendus ne produisent que des variables char *, alors peut-être devriez-vous essayer d'utiliser le c_str() fonction membre pour convertir un std::wstring et ensuite le sortir dans le fichier. Alors ça devrait probablement marcher?


0
2017-10-29 16:43



Vous devriez ne pas Utilisez le fichier source codé UTF-8 si vous souhaitez écrire du code portable. Pardon.

  std :: wstring str = L "abcàdëefŸg € hhhhhhhμa";

(Je ne suis pas sûr que cela blesse réellement le standard, mais je pense que oui. Mais même si, pour être sûr, vous ne devriez pas.)

Oui, purement utiliser std::ostreamne fonctionnera pas. Il existe plusieurs façons de convertir un wstring à UTF-8. Mon préféré utilise la Composants internationaux pour Unicode. C'est une grande lib, mais c'est génial. Vous obtenez beaucoup d'extras et de choses dont vous pourriez avoir besoin à l'avenir.


0
2017-10-29 17:41



D'après mon expérience de travail avec différents encodages de caractères, je vous recommande de ne gérer que UTF-8 en charge et de gagner du temps. Vous êtes dans un monde de douleur si vous essayez de stocker la représentation interne dans UTF-8 car un seul caractère peut avoir de 1 à 4 octets. Ainsi, des opérations simples comme strlen nécessitent de regarder chaque octet pour décider len plutôt que tampon alloué (bien que vous puissiez optimiser en regardant le premier octet dans la séquence de caractères, par exemple 00..7f est un caractère à un seul octet, c2..df indique un caractère à 2 octets, etc.).

Les gens se réfèrent assez souvent aux «chaînes Unicode» quand ils signifient UTF-16 et sous Windows, un wchar_t est un octet fixe. Dans Windows, je pense que wchar_t est simplement:

typedef SHORT wchar_t;

La représentation complète de 4 octets UTF-32 est rarement nécessaire et très inutile, voici ce que le standard Unicode (5.0) a à dire:

"En moyenne, plus de 99% de tous les UTF-16 sont exprimés à l'aide d'unités à code unique ... UTF-16 fournit le bon mélange de taille compacte avec la possibilité de gérer le caractère occasionnel en dehors du BMP"

En bref, utilisez whcar_t comme représentation interne et effectuez des conversions lors du chargement et de l’enregistrement (et ne vous souciez pas de l’Unicode complet, sauf si vous en avez besoin).

En ce qui concerne la réalisation de la conversion, consultez le projet ICU:

http://site.icu-project.org/


0
2017-10-29 17:48



J'ai eu le même problème il y a quelque temps et j'ai écrit la solution que j'ai trouvée sur mon blog. Vous pourriez vouloir le vérifier pour voir si cela peut aider, en particulier la fonction wstring_to_utf8.

http://pileborg.org/b2e/blog5.php/2010/06/13/unicode-utf-8-and-wchar_t


0
2017-10-29 17:08