Подтвердить что ты не робот

Какая кодировка - это имена файлов в NTFS, хранящиеся как?

Я только начинаю программировать для обработки имен файлов с неанглийскими именами в системе WinXP. Я сделал некоторые рекомендуемые чтения в Юникоде, и я думаю, что получаю основную идею, но некоторые части до сих пор не очень понятны мне.

В частности, какая кодировка (UTF-8, UTF-16LE/BE) является файлом имен (а не содержимым, а фактическим именем файла), хранящимся в NTFS? Можно ли открыть любой файл, используя fopen(), который принимает char *, или у меня нет выбора, кроме как использовать wfopen(), который использует wchar_t * и предположительно принимает строку UTF-16?

Я попробовал вручную подать в кодированную строку UTF-8 для fopen(), например.

unsigned char filename[] = {0xEA, 0xB0, 0x80, 0x2E, 0x74, 0x78, 0x74, 0x0}; // 가.txt

FILE* f = fopen((char*)filename, "wb+");

но это получилось как 'ê ° €.txt'.

Я был под впечатлением (что может быть неправильно), что строка с кодировкой UTF8 будет достаточной для открытия любого имени файла под Windows, потому что я, кажется, смутно помню некоторое приложение Windows, проходящее вокруг (char *), а не (wchar_t *) и не имеет проблем.

Может ли кто-нибудь пролить свет на это?

4b9b3361

Ответ 1

NTFS хранит имена файлов в UTF-16, однако fopen использует ANSI (не UTF-8).

Чтобы использовать имя файла в кодировке UTF16, вам нужно будет использовать Unicode-версии вызовов открытия файлов. Сделайте это, определив UNICODE и _UNICODE в своем проекте. Затем используйте вызов CreateFile или вызов wfopen.

Ответ 2

fopen() - в MSVC на окнах нет (по умолчанию) принимают закодированный utf-8 char *.

К сожалению, utf-8 был изобретен сравнительно недавно в великой схеме вещей. API Windows разделены на Unicode и Ansi. все окна api, которые принимают или имеют дело со строками, действительно доступны с суффиксом W или - W для символа "Wide" /Unicode и A для Ansi. Макро-магия скрывает все это от разработчика, поэтому вы просто вызываете CreateFile с помощью char * или wchar_t * в зависимости от конфигурации сборки, не зная разницы.

Кодирование "Ansi" на самом деле не является конкретной кодировкой: - Но означает, что кодировка, используемая для строк "char", специфична для настроек локали ПК.

Теперь, поскольку функции c-runtime - например fopen - должны работать по умолчанию без знаний разработчика - в системах Windows они ожидают получить свои строки в локальной кодировке Windows. msdn указывает, что microsoft c-runtime api setlocal может изменить локаль текущего потока, но в частности говорит, что он будет терпеть неудачу для любых локалей, для которых требуется больше 2 байтов на символ - например, utf-8.

Итак, в Windows нет ярлыка. Вам нужно использовать wfopen или собственный API CreateFileW (или создать проект с использованием настроек сборки Unicode и просто вызвать Createfile) с помощью строк wchar_t *.

Ответ 3

По словам других, лучший способ обработки строк в кодировке UTF-8 - это преобразовать их в UTF-16 и использовать собственные API-интерфейсы Unicode, такие как _wfopen или CreateFileW.

Однако этот подход не поможет при обращении к библиотекам, которые безоговорочно используют fopen() поскольку они не поддерживают Unicode или потому, что они написаны на переносимом C. В этом случае все еще можно использовать устаревшие "короткие пути". чтобы преобразовать строку в кодировке UTF-8 в форму ASCII, используемую с fopen, но это требует некоторого труда:

  1. Преобразуйте представление UTF-8 в UTF-16, используя MultiByteToWideChar.

  2. Используйте GetShortPathNameW чтобы получить "короткий путь", который только для ASCII. GetShortPathNameW вернет его в виде широкой строки со всем содержимым ASCII, которое вам потребуется для тривиального преобразования в узкую строку с помощью копии без потерь, разыгрывающей каждый char wchar_t.

  3. Передайте короткий путь к fopen() или к коду, который в конечном итоге будет использовать fopen(). Имейте в виду, что сообщения об ошибках, напечатанные этим кодом, если они есть, будут ссылаться на неприглядный "короткий путь" (например, KINTO~1 вместо kinto-un-筋斗雲).

Хотя это не совсем рекомендуемая долгосрочная стратегия, поскольку короткие пути Windows являются устаревшей функцией, которую можно отключить для каждого тома, вероятно, это единственный способ передать имена файлов в код, который использует fopen() и другие file- связанные вызовы API (stat, access, ANSI-версии CreateFile и аналогичные).