В какой кодировке хранятся имена файлов в 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*) и имели Нет проблем.
Может кто-нибудь пролить некоторый свет на это?
3 ответа
NTFS хранит имена файлов в UTF16, однако fopen использует ANSI (не utf8).
Чтобы использовать имя файла в кодировке UTF16, вам нужно будет использовать Unicode-версии вызовов открытия файлов. Сделайте это, определив UNICODE и _UNICODE в вашем проекте. Затем используйте вызов CreateFile или вызов wfopen.
fopen() - в MSVC для Windows (по умолчанию) не принимает кодированный в кодировке utf-8 *.
К сожалению, utf-8 был изобретен сравнительно недавно в великолепной схеме вещей. Windows API делятся на версии Unicode и Ansi. каждое окно API, которое принимает или имеет дело со строками, фактически доступно с суффиксом W или A - W для "широкого" символа /Unicode и A для Ansi. Макро-магия скрывает все это от разработчика, поэтому вы просто вызываете CreateFile с типом char* или wchar_t* в зависимости от конфигурации вашей сборки, не зная разницы.
Кодировка 'Ansi' на самом деле не является специфической кодировкой:- Но это означает, что кодировка, используемая для строк "char", специфична для настройки языка ПК.
Теперь, поскольку функции времени выполнения c - такие как fopen - должны работать по умолчанию без ведома разработчика - в системах Windows они ожидают получить свои строки в локальной кодировке Windows. msdn указывает, что API-интерфейс Microsoft c-runtime может изменить локаль текущего потока, но, в частности, говорит, что он потерпит неудачу для любых локалей, которым требуется более 2 байтов на символ - например, utf-8.
Итак, на Windows нет ярлыка. Вам нужно использовать wfopen или нативный API CreateFileW (или создать свой проект с использованием параметров сборки Unicode и просто вызвать Createfile) со строками wchar_t*.
Как ответили другие, лучший способ обработки строк в кодировке UTF-8- это преобразовать их в Unicode и использовать собственные API-интерфейсы Unicode, такие как _wfopen
или же CreateFileW
,
Однако этот подход не поможет при обращении к библиотекам, которые используют fopen()
безусловно, потому что они не поддерживают Unicode или потому что они написаны на переносимом C. В этом случае все еще можно использовать устаревшие "короткие пути" для преобразования строки в кодировке UTF-8 в форму ASCII, которую можно использовать с fopen
, но это требует некоторого труда:
Преобразуйте представление UTF-8 в UTF-16, используя
MultiByteToWideChar
,использование
GetShortPathNameW
чтобы получить "короткий путь", который только для ASCII.GetShortPathNameW
вернет его в виде широкой строки с содержимым, полностью поддерживающим ASCII, которое вам потребуется для простого преобразования в узкую строку путем приведения копии без потерь при каждомwchar_t
char
,Пройдите короткий путь к
fopen()
или к коду, который в конечном итоге будет использоватьfopen()
, Помните, что сообщения об ошибках, напечатанные этим кодом, если таковые имеются, будут ссылаться на неприглядный "короткий путь" (например,KINTO~1
вместоkinto-un-筋斗雲
).
Хотя это не совсем рекомендуемая долгосрочная стратегия, поскольку короткие пути Windows являются устаревшей функцией, которую можно отключить для каждого тома, вероятно, это единственный способ передать имена файлов в код, который использует fopen()
и другие вызовы API, связанные с файлами (stat
, access
ANSI версии CreateFile
и тому подобное).