Какая кодировка - это имена файлов в 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 *) и не имеет проблем.
Может ли кто-нибудь пролить свет на это?
Ответы
Ответ 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
, но это требует некоторого труда:
-
Преобразуйте представление UTF-8 в UTF-16, используя MultiByteToWideChar
.
-
Используйте GetShortPathNameW
чтобы получить "короткий путь", который только для ASCII. GetShortPathNameW
вернет его в виде широкой строки со всем содержимым ASCII, которое вам потребуется для тривиального преобразования в узкую строку с помощью копии без потерь, разыгрывающей каждый char
wchar_t
.
-
Передайте короткий путь к fopen()
или к коду, который в конечном итоге будет использовать fopen()
. Имейте в виду, что сообщения об ошибках, напечатанные этим кодом, если они есть, будут ссылаться на неприглядный "короткий путь" (например, KINTO~1
вместо kinto-un-筋斗雲
).
Хотя это не совсем рекомендуемая долгосрочная стратегия, поскольку короткие пути Windows являются устаревшей функцией, которую можно отключить для каждого тома, вероятно, это единственный способ передать имена файлов в код, который использует fopen()
и другие file- связанные вызовы API (stat
, access
, ANSI-версии CreateFile
и аналогичные).