¿En qué encoding están almacenados los nombres de archivo en NTFS?

Estoy empezando con algunos progtwigs para manejar nombres de archivos con nombres que no sean en inglés en un sistema WinXP. He hecho algunas lecturas recomendadas en Unicode y creo que entiendo la idea básica, pero algunas partes aún no son muy claras para mí.

Específicamente, ¿qué encoding (UTF-8, UTF-16LE / BE) son los nombres de archivo (no el contenido, sino el nombre real del archivo) almacenados en NTFS? ¿Es posible abrir cualquier archivo usando fopen (), que toma un char *, o no tengo otra opción que usar wfopen (), que usa un wchar_t *, y presumiblemente toma una cadena UTF-16?

Intenté alimentar manualmente en una cadena codificada en UTF-8 a fopen (), por ej.

unsigned char filename[] = {0xEA, 0xB0, 0x80, 0x2E, 0x74, 0x78, 0x74, 0x0}; // 가.txt FILE* f = fopen((char*)filename, "wb+"); 

pero esto salió como ‘ê ° € .txt’.

Tenía la impresión (que puede ser errónea) de que una cadena codificada en UTF8 sería suficiente para abrir cualquier nombre de archivo en Windows, porque parece recordar vagamente alguna aplicación de Windows que pasa (char *), no (wchar_t *) y tener no hay problemas.

¿Alguien puede arrojar algo de luz sobre esto?

NTFS almacena nombres de archivo en UTF16, sin embargo fopen usa ANSI (no utf8).

Para usar un nombre de archivo codificado en UTF16, necesitará usar las versiones Unicode del archivo de llamadas abiertas. Haga esto definiendo UNICODE y _UNICODE en su proyecto. Luego use la llamada CreateFile o la llamada wfopen.

fopen () – en MSVC en Windows no toma (por defecto) un char * codificado para utf-8.

Lamentablemente, utf-8 se inventó recientemente en el gran esquema de cosas. Las API de Windows están divididas en versiones de Unicode y Ansi. cada api de Windows que toma o trata con cadenas está realmente disponible con un sufijo W o A – W para caracteres “Anchos” / Unicode y A para Ansi. La magia de macro oculta todo esto lejos del desarrollador, así que simplemente llama a CreateFile con un char * o un wchar_t * según la configuración de tu comstackción sin saber la diferencia.

La encoding ‘Ansi’ no es en realidad una encoding específica: – Significa que la encoding utilizada para las cadenas “char” es específica de la configuración regional de la PC.

Ahora, debido a que las funciones de c-runtime, como fopen, deben funcionar de manera predeterminada sin el conocimiento del desarrollador, en los sistemas de Windows esperan recibir sus cadenas en la encoding local de Windows. msdn indica que el aplo setlocal de c-runtime de microsoft puede cambiar la configuración regional del hilo actual, pero específicamente dice que fallará para cualquier configuración regional que necesite más de 2 bytes por carácter, como utf-8.

Entonces, en Windows no hay atajo. Necesita usar wfopen, o la API nativa CreateFileW (o cree su proyecto usando la configuración de comstackción Unicode y simplemente llame a Createfile) con cadenas wchar_t *.

Como respondieron otros, la mejor forma de manejar cadenas codificadas en UTF-8 es convertirlas a Unicode y usar API Unicode nativas como _wfopen o _wfopen .

Sin embargo, este enfoque no ayudará cuando se invoca en bibliotecas que usan fopen() incondicionalmente porque no admiten Unicode o porque están escritas en C portátil. En ese caso, aún es posible hacer uso de los “caminos cortos” heredados. para convertir una cadena codificada en UTF-8 en una forma ASCII utilizable con fopen , pero requiere algo de trabajo de campo:

  1. Convierta la representación UTF-8 a UTF-16 usando MultiByteToWideChar .

  2. Use GetShortPathNameW para obtener una “ruta corta” que es solo ASCII. GetShortPathNameW lo devolverá como una cadena ancha con contenido totalmente ASCII, que necesitará convertir trivialmente a una cadena estrecha mediante una copia sin pérdida que wchar_t cada char wchar_t .

  3. Pase la ruta corta a fopen() o al código que eventualmente usará fopen() . Tenga en cuenta que los mensajes de error impresos por ese código, si los hay, se referirán a la antiestética “ruta corta” (por ejemplo, KINTO~1 lugar de kinto-un-筋斗雲 ).

Si bien esta no es exactamente una estrategia recomendada a largo plazo, dado que las rutas cortas de Windows son una función heredada que se puede desactivar por volumen, es probable que la única forma de pasar nombres de archivos al código que usa fopen() y otros archivos- llamadas a API relacionadas ( stat , access , versiones ANSI de CreateFile y similares).