уже есть несколько вопросов, связанных с этой проблемой. Я думаю, что мой вопрос немного другой, потому что у меня нет реальной проблемы, я просто спрашиваю академических интересов. Я знаю, что реализация UTF-16 в Windows иногда противоречит стандарту Unicode (например, сортировке) или ближе к старой UCS-2, чем к UTF-16, но я буду придерживаться терминологии "UTF-16" по причинам простота.
Фон: в 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 и С++, похоже, придерживаются устаревшей модели кодировки. Как бы вы разработали API Windows или инфраструктуру приложения, чтобы обойти эту проблему?
Я думаю, что общая проблема (что нелегко решить) состоит в том, что все библиотеки предполагают, что все потоки байт-ориентированы, а поверх них также используются текстовые потоки. Однако мы видим, что Windows имеет специальные текстовые потоки на уровне ОС, и библиотеки не могут справиться с этим. Поэтому в любом случае мы должны внести существенные изменения во все стандартные библиотеки. Быстрым и грязным способом было бы рассматривать консоль как специальный поток, ориентированный на байты, который принимает только одну кодировку. Это по-прежнему требует, чтобы стандартные библиотеки C и С++ были обойдены, поскольку они не реализуют переключатель WriteFile
/WriteConsoleW
. Это правильно?