есть еще несколько вопросов, связанных с этой проблемой. Я думаю, что мой вопрос немного другой, потому что у меня нет реальной проблемы, я просто спрашиваю академических интересов. Я знаю, что реализация Windows UTF-16 иногда противоречит стандарту Unicode (например, сортировке) или ближе к старой UCS-2, чем к UTF-16, но я буду придерживаться терминологии «UTF-16» по причинам простота.Как вывести строки Unicode на консоли Windows
Фон: В Windows все UTF-16. Независимо от того, имеете ли вы дело с ядром, графической подсистемой, файловой системой или любым другим, вы передаете строки UTF-16. В смысле Unix нет локалей или кодировок. Для совместимости со средневековыми версиями Windows есть вещь, называемая «кодовыми страницами», которая устарела, но тем не менее поддерживается. AFAIK существует только одна правильная и не устаревшая функция для записи строк в консоль, а именно: WriteConsoleW
, которая принимает строку UTF-16. Кроме того, аналогичное обсуждение применяется к входным потокам, которые я также игнорирую.
Однако, я думаю, что это представляет собой дефект дизайна в Windows API: существует общая функция, которая может использоваться для записи во все объекты потока (файлы, трубы, консоли ...), называемые WriteFile
, но эта функция является байт- ориентированы и не принимают строки UTF-16. В документации предлагается использовать WriteConsoleW
для вывода на консоль, который является текстовым, и WriteFile
для всего остального, байт-ориентированного. Поскольку потоки консоли и файловые объекты представлены обработчиками объектов ядра, а потоки консолей можно перенаправить, вы должны вызвать функцию для каждой записи в стандартный выходной поток, который проверяет, является ли дескриптор консольным потоком или файлом, нарушая полиморфность. OTOH, я думаю, что разделение Windows между текстовыми строками и необработанными байтами (которое отражается во многих других системах, таких как Java или Python) концептуально превосходит подход Unix char*
, который игнорирует кодировки и не различает строки и байтовые массивы.
Итак, мои вопросы: что делать в этой ситуации? И почему эта проблема не решена даже в собственных библиотеках Microsoft? Как библиотеки .NET Framework, так и библиотеки C и C++, похоже, придерживаются устаревшей модели кодировки. Как бы вы разработали API Windows или инфраструктуру приложения, чтобы обойти эту проблему?
Я думаю, что общая проблема (что нелегко решить) состоит в том, что все библиотеки предполагают, что все потоки байт-ориентированы и используют поверх них потоки, ориентированные на текст. Однако мы видим, что Windows имеет специальные текстовые потоки на уровне ОС, и библиотеки не могут справиться с этим. Поэтому в любом случае мы должны внести существенные изменения во все стандартные библиотеки. Быстрым и грязным способом было бы рассматривать консоль как специальный поток, ориентированный на байты, который принимает только одну кодировку. Это по-прежнему требует, чтобы стандартные библиотеки C и C++ были обойдены, поскольку они не реализуют переключатель WriteFile
/WriteConsoleW
. Это верно?
извините, этот «вопрос» звучит как запись в блоге в маскировке ;-) – Philipp
это может быть связано с моим вопросом: http://superuser.com/questions/157225/even-on-windows-7- can-you-do-a-dir-and-be-able-to-see-filenames-that-has-unico –