Lire le fichier Unicode UTF-8 dans wstring
Comment puis-je lire un fichier Unicode (UTF-8) dans wstring
(s) sur la plate-forme Windows?
6 réponses
avec le support C++11, Vous pouvez utiliser std::codecvt_utf8 facet qui encapsule la conversion entre une chaîne D'octets encodée UTF-8 et la chaîne de caractères UCS2 ou UCS4 et qui peut être utilisée pour lire et écrire des fichiers UTF-8, texte et binaire.
pour utiliser facet vous créez habituellement locale object qui encapsule l'information propre à la culture comme un ensemble de facettes qui définissent collectivement un environnement localisé spécifique. une fois que vous avez un objet local, vous pouvez imbue votre tampon de flux avec elle:
#include <sstream>
#include <fstream>
#include <codecvt>
std::wstring readFile(const char* filename)
{
std::wifstream wif(filename);
wif.imbue(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));
std::wstringstream wss;
wss << wif.rdbuf();
return wss.str();
}
qui peut être utilisé comme ceci:
std::wstring wstr = readFile("a.txt");
alternativement vous pouvez définir la locale c++ globale avant de travailler avec les flux de chaîne de caractères qui provoque tous les appels futurs à la std::locale
constructeur par défaut pour retourner une copie de la locale c++ globale (vous n'avez pas besoin d'y intégrer explicitement des tampons stream):
std::locale::global(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));
selon un commentaire de @Hans Passant, la manière la plus simple est d'utiliser _wfopen_s . Ouvrez le fichier en mode rt, ccs=UTF-8
.
Voici une autre solution pure C++ qui fonctionne au moins avec VC++ 2010:
#include <locale>
#include <codecvt>
#include <string>
#include <fstream>
#include <cstdlib>
int main() {
const std::locale empty_locale = std::locale::empty();
typedef std::codecvt_utf8<wchar_t> converter_type;
const converter_type* converter = new converter_type;
const std::locale utf8_locale = std::locale(empty_locale, converter);
std::wifstream stream(L"test.txt");
stream.imbue(utf8_locale);
std::wstring line;
std::getline(stream, line);
std::system("pause");
}
sauf pour locale::empty()
(ici locale::global()
pourrait fonctionner aussi bien) et la wchar_t*
surcharge du basic_ifstream
constructeur, cela devrait même être assez conforme à la norme (où "standard" signifie C++0x, bien sûr).
Voici une fonction spécifique à la plate-forme pour Windows seulement:
size_t GetSizeOfFile(const std::wstring& path)
{
struct _stat fileinfo;
_wstat(path.c_str(), &fileinfo);
return fileinfo.st_size;
}
std::wstring LoadUtf8FileToString(const std::wstring& filename)
{
std::wstring buffer; // stores file contents
FILE* f = _wfopen(filename.c_str(), L"rtS, ccs=UTF-8");
// Failed to open file
if (f == NULL)
{
// ...handle some error...
return buffer;
}
size_t filesize = GetSizeOfFile(filename);
// Read entire file contents in to memory
if (filesize > 0)
{
buffer.resize(filesize);
size_t wchars_read = fread(&(buffer.front()), sizeof(wchar_t), filesize, f);
buffer.resize(wchars_read);
buffer.shrink_to_fit();
}
fclose(f);
return buffer;
}
utiliser comme suit:
std::wstring mytext = LoadUtf8FileToString(L"C:\MyUtf8File.txt");
notez que le fichier entier est chargé en mémoire, donc vous ne voudrez peut-être pas l'utiliser pour de très gros fichiers.
#include <iostream>
#include <fstream>
#include <string>
#include <locale>
#include <cstdlib>
int main()
{
std::wifstream wif("filename.txt");
wif.imbue(std::locale("zh_CN.UTF-8"));
std::wcout.imbue(std::locale("zh_CN.UTF-8"));
std::wcout << wif.rdbuf();
}
cette question a été abordée dans confus au sujet de C++'S std::wstring, UTF-16, UTF-8 et l'affichage de chaînes dans une interface graphique windows . En résumé, wstring est basé sur la norme UCS-2, qui est le prédécesseur de UTF-16. Cette activité est strictement deux octets standard. Je crois que ce couvre arabe.
c'est un peu brut, mais que diriez-vous de lire le fichier comme de vieux octets puis de lancer le tampon byte vers wchar_t* ?
quelque chose comme:
#include <iostream>
#include <fstream>
std::wstring ReadFileIntoWstring(const std::wstring& filepath)
{
std::wstring wstr;
std::ifstream file (filepath.c_str(), std::ios::in|std::ios::binary|std::ios::ate);
size_t size = (size_t)file.tellg();
file.seekg (0, std::ios::beg);
char* buffer = new char [size];
file.read (buffer, size);
wstr = (wchar_t*)buffer;
file.close();
delete[] buffer;
return wstr;
}