problème à l'aide de getline avec un fichier unicode
Mise à JOUR: Merci à @Potatoswatter et @Jonathan Leffler pour commentaires - plutôt embarrassante j'ai été surpris par l'outil de débogage de la pointe ne montrant pas la valeur d'un wstring correctement - mais il n'est toujours pas assez de travail pour moi et j'ai mis à jour la question ci-dessous:
Si j'ai un petit multi-octets du fichier que je veux lire une chaîne de caractères-je utiliser l'astuce suivante - je utiliser getline
avec un délimiteur de '\0'
par exemple
std::string contents_utf8;
std::ifstream inf1("utf8.txt");
getline(inf1, contents_utf8, 'std::string contents_utf8;
std::ifstream inf1("utf8.txt");
getline(inf1, contents_utf8, '\0');
');
Ce lit dans l'ensemble du dossier, y compris les retours à la ligne.
Cependant, si j'essaie de faire la même chose avec un caractère large de fichier ne fonctionne pas - mon wstring
ne lit à la première ligne.
std::wstring contents_wide;
std::wifstream inf2(L"ucs2-be.txt");
getline( inf2, contents_wide, wchar_t(0) ); //doesn't work
Par exemple si mon fichier unicode contient les caractères A et B séparés par un CRLF, la tête ressemble à ceci:
FE FF 00 41 00 0D 00 0A 00 42
Basé sur le fait que, avec un multi-octets du fichier getline avec '\0' lit le fichier en entier j'ai cru que getline( inf2, contents_wide, wchar_t(0) )
peut lire l'intégralité du fichier unicode. Cependant, il n'est pas - avec l'exemple au-dessus de ma grande chaîne contiendra les deux wchar_ts: FF FF
(Si je retire la wchar_t(0) on lit à la première ligne, comme prévu (c'est à dire FE FF 00 41 00 0D 00
)
Pourquoi ne pas wchar_t(0) travaillent en délimitant wchar_t de sorte que getline s'arrête sur 00 00
(ou lit à la fin du fichier, qui est ce que je veux)?
Merci
- Le multi-octets fichier doit lire à '\n', n'est-ce pas? Idem pour les caractères larges de la version, il convient de lire pour le grand caractère de saut de ligne.
- UCS-2 ne devrait pas faire de traduction, de sorte qu'il ne peut pas être la machine de l'etat. Cela fonctionne correctement si vous n'avez pas de
\0
s? - Leffler la MO fichier se lit à l'EOF (y compris \n) parce que j'ai dit que le délimiteur de s'arrêter sur est 0
- même résultat pour le widechar version résultat, si je retire la whar_t(0) arrête la lecture à la première de 0 octet.
- non, je veux dire ce qui se passe si il n'y a pas de 0 octets dans le fichier. Aussi, n'est-ce pas "arrêt de la lecture à la première de 0 octet" ce que vous avez demandé? Il serait utile si vous avez été plus précis. Faut-il agir comme le 0 de l'octet est la fin du fichier? Ce n'est pas ce que votre description ressemble.
- La Correction (j'ai été surpris par le débogueur pas en me montrant la chaîne correctement) si je retire la wchar_t(0) ensuite, il lit à la fin de la première ligne que l'on pourrait attendre
Vous devez vous connecter pour publier un commentaire.
Votre UCS-2 decoder est défaillante. Le résultat de
getline( inf2, contents_wide )
surFE FF 00 41 00 0D 00 0A 00 42
devrait être0041 0000
=L"A"
. En supposant que vous êtes sur Windows, les caractères de fin de ligne doit être converti correctement, et la marque d'ordre d'octet ne devrait pas apparaître dans la sortie.Suggérons de vérifier votre documentation du système d'exploitation à l'égard de la façon dont vous définissez les paramètres régionaux.
EDIT: Avez-vous définissez les paramètres régionaux?
ou
où encoding_support est une bibliothèque.
Voir cette question: Pourquoi l'échelle de fichier en C++ étroit écrites données par défaut?, où l'affiche est surpris par la
wchar_t
->char
de conversion lors de l'écriture.Les réponses données à cette question s'applique à la lecture des cas aussi. En un mot: au niveau le plus bas, e/S de fichier est toujours fait en termes d'octets. Un
basic_filebuf
(ce que l'fstream
utilise pour effectuer réellement les I/O) utilise unecodecvt
facette à la traduction entre les "internes" de l'encodage (le type char vu par le programme, et utilisé pour instancier le flux,wchar_t
dans votre cas) et "externes" de l'encodage du fichier (qui est toujourschar
).La
codecvt
est obtenu à partir du fluxlocale
. Si aucune localisation n'estimbue()
-d sur le flux, le mondial locale est utilisée. Par défaut, le mondial locale est le "classique" (ou "C") paramètres régionaux. Que les paramètres régionaux de l'codecvt
facette est assez basique. Je ne sais pas ce que dit la norme à ce sujet, mais, dans mon expérience, sur Windows, il suffit simplement de "jette" entrechar
etwchar_t
, un par un. Sur Linux, il le fait aussi, mais échoue si le caractère de la valeur est en dehors de la plage ASCII.Donc, si vous ne touchez pas à la locale (soit par
imbue()
-ing un sur la rivière ou de la modification de la global), ce qui arrivera probablement dans votre cas est quechar
s sont lus à partir du fichier et de lancer pourwchar_t
un par un. Ainsi, il lit d'abordFF
, puisFE
, puis00
, etgetline(..., 0)
s'arrête là.L"ucs2-be.txt" regarde-moi comme un drapeau pour big endian, mais la matrice FE FF 00 41 00 0D 00 0A 00 42 ressemble little-endian. Je suppose que c'est pourquoi la FE FF caractère a été lu dans votre tableau au lieu d'être ignorée. Je ne peux pas comprendre pourquoi la présence ou l'absence de wchar(0) affecte les résultats si.