Прежде всего, что является именем файла?
В Unix-подобных системах
Имя файла - последовательность байтов , оканчивающаяся нануль.Ядру не нужно заботиться о кодировке символов (кроме как знать код ASCII для /
).
Однако с точки зрения пользователей удобнее интерпретировать имена файлов как последовательности символы , и это делается с помощью кодировки символов , указанной как часть языкового стандарта . Юникод поддерживается благодаря обеспечению доступности языковых стандартов UTF-8.
В программах на C файлы представлены обычными char*
строками в таких функциях, как fopen
. Не существует широкоформатной версии POSIX API. Если у вас есть wchar_t*
имя файла, вы должны явно преобразовать его в char*
.
В Windows NT
Имя файла последовательность кодовых единиц UTF-16 .Фактически, все манипулирование строками в Windows выполняется внутри UTF-16.
Все библиотеки Microsoft C (++), включая библиотеку времени выполнения Visual C ++, используют соглашение, *Строки 1038 * находятся в устаревшей кодовой странице ANSI для конкретной локали, а строки wchar_t*
- в UTF-16.А функции char*
являются просто оболочками с обратной совместимостью для новых функций wchar_t*
.
Итак, если вы вызываете MessageBoxA(hwnd, text, caption, type)
, это по сути то же самое, что и вызов MessageBoxW(hwnd, ToUTF16(text), ToUTF16(caption), type)
,И когда вы вызываете fopen(filename, mode)
, это похоже на _wfopen(ToUTF16(filename), ToUTF16(mode))
.
Обратите внимание, что _wfopen
является одной из многих нестандартных функций C для работы со строками wchar_t*
.И это не только для удобства; вы не можете использовать стандартные char*
эквиваленты , поскольку они ограничивают вас кодовой страницей "ANSI" (которая не может быть UTF-8 ),Например, в локали windows-1252 вы не можете (легко) fopen
файл שלום.c
, потому что просто невозможно представить эти символы в узкой строке.
В кроссплатформенномбиблиотеки
Вот некоторые типичные подходы:
- Используйте стандартные функции C со строками
char*
, и просто не давайте ? о поддержке не-ANSI символов в Windows. - Используйте
char*
строки, но интерпретируйте их как UTF-8 вместо ANSI.В Windows напишите функции-оболочки, которые принимают аргументы UTF-8, преобразуют их в UTF-16 и вызывают такие функции, как _wfopen
. - . Повсеместно используйте широкие символьные строки, что похоже на №2, за исключением того, что вам нужнонаписать функции-оболочки для не -Windows систем.
Как zlib обрабатывает имена файлов?
К сожалению, похоже, что используется наивный подход # 1 выше, сopen
(а не _wopen
) используется напрямую.
Как вы можете обойти это?
Помимо уже упомянутых решений (мое любимое из них - предложение gzdopen
Appleman1234),Вы можете воспользоваться символьными ссылками , чтобы дать файлу альтернативное полностью ASCII-имя, которое затем можно безопасно передать gzopen
.Возможно, вам даже не придется делать это, если файл уже имеет подходящее короткое имя .