Кодовая страница Windows Взаимодействие со стандартными именами файлов C / C ++? - PullRequest
5 голосов
/ 26 января 2009

Клиент жалуется, что наш код используется для записи файлов с японскими символами в имени файла, но больше не работает во всех случаях. Мы всегда просто использовали старые добрые строки char * для представления имен файлов, поэтому для меня стало шоком то, что это сработало, и мы не сделали ничего, что, как мне известно, могло бы заставить его перестать работать. Я попросил их отправить мне файл со встроенным именем файла, экспортированным из нашего программного обеспечения, и похоже, что строки используют шестнадцатеричные символы 82 и 83 в качестве первого символа двухбайтовой последовательности для представления японских символов. Работа в Интернете заставляет меня поверить, что это, вероятно, SHIFT_JIS и / или кодовая страница Windows 932.

Мне кажется, что то, что происходит, ранее было и fopen, и ofstream :: открытое имя файла с использованием этой кодовой страницы; сейчас только fopen делает. Я проверил документы Visual Studio fopen и не вижу намека на то, что делает приемлемую строку для передачи в fopen.

В краткосрочной перспективе я надеюсь, что кто-то сможет пролить свет на конкретную проблему Windows fopen и ofstream :: open для меня. В долгосрочной перспективе мне бы очень хотелось узнать, как можно открыть Unicode (и другие?) Имена файлов в C ++, в Windows, Linux и OS X.

Отредактировано, чтобы добавить: я считаю, что открытия, которые работают, выполняются в локали "C", тогда как те, которые не работают, выполняются в любой локали клиента по умолчанию. Тем не менее, это имело место в течение многих лет, и старая версия программы все еще работает сегодня в их системе, так что это кажется длинным объяснением для объяснения проблемы, которую мы видим.

Обновление: я отправил небольшую тестовую программу клиенту. Он проверил, что fopen отлично работает с именем файла SHIFT_JIS, а std :: ofstream - нет. Это происходит в Visual Studio 2005 и происходит независимо от того, использовал ли я язык по умолчанию или язык "C".

Мне все еще интересно, есть ли у кого-нибудь объяснение этому поведению (и почему оно загадочно изменилось - возможно, пакет обновления VS2005?), И надеюсь собрать воедино исчерпывающие «лучшие практики» для обработки имен файлов Unicode в переносимом C ++. код.

Ответы [ 6 ]

3 голосов
/ 09 февраля 2009

Функции типа fopen или ofstream :: open принимают имя файла как char *, но это интерпретируется как наличие в кодовой странице системы.

Это означает, что это может быть японский символ, представленный как Shift-JIS (cp932), или упрощенный китайский (Big 5 / cp936), корейский, арабский, русский, назовите его (при условии, что он совпадает с системным кодом ОС) страница).

Это также означает, что он может использовать японские имена файлов только в японской системе. Измените системную кодовую страницу, и приложение «перестает работать» Я подозреваю, что это то, что происходит здесь (в Windows 2000 нет больших изменений в этой области).

Вот как вы можете изменить системную кодовую страницу: http://www.mihai -nita.net / article.php? ArtID = 20050611a

В долгосрочной перспективе вы можете рассмотреть возможность перехода на Unicode (и использовать _wfopen, wofstream).

2 голосов
/ 03 февраля 2009

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

  • для C: glib использует имена файлов в UTF-8;
  • для C ++: glibmm также использует имена файлов в UTF-8, требует glib;
  • для C ++: boost может использовать wstring для имен файлов.

Я почти уверен, что .NET / mono-фреймворки также содержат функции переносимых файловых систем, но я их не знаю.

0 голосов
/ 09 августа 2013

Кто-то все еще смотрит это? Я только что исследовал этот вопрос и нигде не нашел ответов, поэтому я могу попытаться объяснить свои выводы здесь.

В VS2005 обработка имени файла fstream выглядит странно: она не использует системную кодировку по умолчанию, ту, которую вы получаете с GetACP и задаете в Панели управления / Регион и Язык / Административный. Но всегда CP 1252 - я верю.

Это может вызвать большую путаницу, и Microsoft удалила эту причуду в более поздних версиях VS.

Все обходные пути для VS2005 имеют свои недостатки:

  1. Преобразование кода для повсеместного использования Юникода

  2. Никогда не открывайте потоки, используя имена файлов с узкими символами, всегда конвертируйте их в Unicode, используя собственную кодировку системы по умолчанию, используйте имя файла широких символов open / ctor

  3. Извлеките кодовую страницу, используя GetACP (), затем выполните

соответствующий setlocale:

setlocale (LC_ALL, ("." + lexical_cast<string> (GetACP())).c_str())
0 голосов
/ 05 февраля 2009

Mac OS X использует Unicode в качестве родной кодировки символов. Основными строковыми объектами являются CFString и NSString. Они хранят массив символов как Unicode.

0 голосов
/ 26 января 2009

Возможно, вам придется установить языковой стандарт потока в системный языковой стандарт по умолчанию. Смотрите здесь для возможной причины ваших проблем: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100887

0 голосов
/ 26 января 2009

Я почти уверен, что в Linux строка имени файла представляет собой строку UTF-8 (например, в файловой системе EXT3 единственными запрещенными символами являются косая черта и NULL), которые хранятся в обычном char *. На странице руководства, похоже, не упоминается кодировка символов, и именно поэтому я считаю, что это системный стандарт UTF-8. OS X, вероятно, использует то же самое, поскольку оно происходит от похожих корней, но я менее уверен в этом.

...