¿Cómo puedo leer un archivo Unicode (UTF-8) en wstring
(s) en la plataforma de Windows?Lea el archivo Unicode UTF-8 en wstring
Respuesta
Respondió esta pregunta en Confused about C++'s std::wstring, UTF-16, UTF-8 and displaying strings in a windows GUI. En resumen, wstring se basa en el estándar UCS-2, que es el predecesor de UTF-16. Este es un estándar estrictamente de dos bytes. Creo que esto cubre el árabe.
Creo que puede usar wstring con UTF-16 –
@Daivd: En realidad, usted es incorrecto, y esto es un malentendido común. UTF-16 cubre 1,112,064 puntos de código de 0 a 0x10FFFF. El esquema requiere un almacenamiento de longitud variable de una o dos palabras de 16 bits, mientras que UCS-2 era estrictamente una palabra de 16 bits. Si rastrea la definición de wchar_t, encontrará que tiene como su raíz es un tipo primitivo de 16 bits (generalmente un corto). – ThomasMcLeod
@David: Técnicamente, un 'wstring' es solo una matriz de enteros de 16 bits en Windows. Puede almacenar datos UCS-2 o UTF-16 o lo que quiera en él. La mayoría de las API de Windows aceptan cadenas UTF-16 hoy en día. – Philipp
Aquí es una función específica de la plataforma para Windows solamente:
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;
}
uso de este modo:
std::wstring mytext = LoadUtf8FileToString(L"C:\\MyUtf8File.txt");
Nota todo el archivo se carga en la memoria, por lo que puede que no desee utilizarlo para archivos muy grandes
También podría funcionar todo el camino: _wfopen (filename.c_str(), L "rt, ccs = UTF-8"); La conversión ahora es automática. –
Gracias, respuesta editada. – AshleysBrain
En realidad, lo recuperó, los documentos de _wfopen dicen que se convierte en caracteres anchos automáticamente, y este código no lo tiene en cuenta. – AshleysBrain
De acuerdo con un comentario de @Hans Passant, la forma más sencilla es usar _wfopen_s. Abra el archivo con el modo rt, ccs=UTF-8
.
Aquí hay otra solución pura de C++ que funciona al menos con 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");
}
excepción de locale::empty()
(aquí locale::global()
podría funcionar también) y la sobrecarga de wchar_t*
del basic_ifstream
constructor, esto aún debe ser bastante estándar-obediente (donde "estándar" significa C++ 0x, por supuesto).
¿Por qué no 'borrar convertidor'? – Mikhail
"Overload 7 se suele llamar con su segundo argumento, f, obtenido directamente de una nueva expresión: la configuración regional es responsable de llamar a la eliminación correspondiente de su propio destructor". [link] (http://en.cppreference.com/w/cpp/locale/locale/locale) – sven
Esto solo lee la primera línea del archivo ... –
Con el apoyo de C++ 11, puede utilizar std::codecvt_utf8 facetque encapsula la conversión entre una cadena de codificación UTF-8 bytes y UCS2 o UCS4 cadena de caracteres y que se puede utilizar para leer y escribir archivos UTF-8, tanto texto y binario
Para utilizar facet por lo general crea locale objectque encapsula la información específica de la cultura como un conjunto de facetas que definen colectivamente un entorno localizado específica. Una vez que tenga un objeto local, puede imbue su búfer de la secuencia con ella:
#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();
}
que puede ser utilizado como esto:
std::wstring wstr = readFile("a.txt");
alternativa, puede configurar the global C++ locale antes de trabajar con corrientes de cuerda, que hace que todas las llamadas futuras al constructor predeterminado std::locale
devuelvan una copia de la configuración regional global de C++ (no es necesario imbuir de manera explícita las memorias intermedias de la secuencia):
std::locale::global(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));
¿Eso 'nuevo codecvt_utf8' requiere un' delete' correspondiente? –
Sin necesidad de eliminar explícitamente codecvt_utf8. Esto se hace en el destructor de std :: locale cuando el refcounter de codecvt_utf8 se convierte en cero (ver http://en.cppreference.com/w/cpp/locale/locale/%7Elocale) – MrTux
Esto es un poco crudo, pero ¿qué hay de leer el archivo como viejos bytes sin formato y luego convertir el búfer de bytes a wchar_t *?
Algo así como:
#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;
}
#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();
}
Hola. Gracias por compartir. Apreciado. ¿Puedes agregar un poco más de contexto? Por qué esta respuesta a una pregunta de 6 años. Gracias. – wp78de
Tengo algunas preguntas recientemente, pero las he solucionado ahora, quiero compartir mi solución para ayudar a otros. –
Eso es bueno. ¿Pero cómo es tu respuesta diferente de la respuesta de @ LihO? Solo usas una configuración regional diferente, ¿verdad? – wp78de
- 1. Lea un archivo con caracteres Unicode
- 2. WebClient Unicode - ¿Qué UTF8?
- 3. Cómo convertir UTF8 a Unicode
- 4. Lea archivos de texto unicode con java
- 5. Convertir punto de código unicode en hex UTF8 en python
- 6. C++ cómo escribir/leer ofstream en Unicode/UTF8
- 7. Lea el archivo con Rhino
- 8. Lea el archivo XML en XmlDocument
- 9. Lea el archivo binario en una estructura
- 10. Lea el archivo codificado UNIX con C#
- 11. Multithreading un archivo masivo lea
- 12. Cómo convertir el archivo * .txt en Unicode
- 13. Lea y sobrescribir un archivo en Python
- 14. lea un archivo MSWord en R
- 15. Lea del archivo de Excel en C
- 16. Lea todo el archivo ASCII en C++ std :: string
- 17. Lea el archivo a una velocidad determinada en Java
- 18. Lea el archivo excel xlsx usando simplexlsx en php
- 19. Lea el archivo XML estático en Google App Engine
- 20. Lea el archivo binario como una cadena en Ruby
- 21. Cómo realizo lecturas aleatorias de un archivo UTF8
- 22. Cómo imprimir wstring en gdb
- 23. ¿Cómo puedo obtener el tamaño de byte de std :: wstring?
- 24. std :: wstring length
- 25. Convirtiendo el problema ANSI en UTF8 C#
- 26. Nuevos caracteres Unicode en C++ 0x
- 27. java: cómo convertir un archivo a utf8
- 28. ¿Cómo agrego un wstring?
- 29. C#, lea las estructuras del archivo binario
- 30. Haskell: lea un archivo por línea
Por "Unicode" Qué quiere decir UTF-8 o UTF-16? ¿Y qué plataforma estás usando? – dan04
utf-8 en Windows – Abdelwahed
Lea este artículo: [Lectura de UTF-8 con flujos de C++] (http: //www.codeproject.com/KB/stl/utf8facet.aspx) – Nawaz