Как GHC / Haskell решает, какую кодировку символов он будет декодировать / кодировать из / в? - PullRequest
12 голосов
/ 13 марта 2011

Кажется, что GHC, по крайней мере, несовместим в кодировке символов, из которой он решает декодировать.

Рассмотрим файл omatase-shimashita.txt со следующим содержимым, закодированным в UTF-8: お 待 た せ し ま100 た

readFile, кажется, правильно читает это ...

Prelude> content <- readFile "/home/chris/Desktop/omatase-shimashita.txt"
Prelude> length content
8
Prelude> putStrLn content
お待たせしました

Однако, если я пишу простой "эхо-сервер", он не декодируется по умолчанию с UTF-8.Рассмотрим следующий код, который обрабатывает входящий клиент:

handleClient handle = do
  line <- hGetLine handle
  putStrLn $ "Read following line: " ++ toString line
  handleClient handle

И соответствующий код клиента, явно отправляющий UTF-8:

Data.ByteString.hPutStrLn handle $ Codec.Binary.UTF8.Generic.fromString "お待たせしました"

Разве это не противоречивое поведение?Есть ли способ этого безумия?Я планирую переписать свои приложения для явного использования ByteString объектов и явного кодирования и декодирования с использованием Codec.Binary.UTF8, но было бы хорошо узнать, что здесь происходит в любом случае ...: o /

ОБНОВЛЕНИЕ: я работаю в Ubuntu Linux версии 10.10 с языком en_US.UTF-8 ...

$ cat /etc/default/locale 
LANG="en_US.UTF-8"
$ echo $LANG 
en_US.UTF-8

Ответы [ 2 ]

6 голосов
/ 14 марта 2011

Ваш первый пример использует стандартную библиотеку ввода-вывода, System.IO.Операции в этой библиотеке используют системную кодировку по умолчанию (также известную как localeEncoding), если не указано иное.Предположительно ваша система настроена на использование UTF-8, так что это кодировка, используемая putStrLn, hGetContents и т. Д.

Во втором примере используется Data.ByteString.Поскольку эта библиотека работает только с последовательностями байтов, она не кодирует и не декодирует.Таким образом, Data.ByteString.hGetLine преобразует байты в файле непосредственно в ByteString.

. В общем, лучший способ сделать ввод / вывод текста в целом - использовать пакет text .

6 голосов
/ 13 марта 2011

Какую версию GHC вы используете?Более старые версии особенно плохо справлялись с вводом / выводом в Юникоде.

В этом разделе документации GHC описано, как изменить кодировки ввода / вывода:

http://haskell.org/ghc/docs/6.12.2/html/libraries/base-4.2.0.1/System-IO.html#23

Кроме того, в документации сказано следующее:

У дескриптора текстового режима есть связанное TextEncoding, которое используется для декодирования байтов в символы Unicode при чтении и кодирования символов Unicode в байты при записи.

По умолчанию TextEncoding совпадает с кодировкой по умолчанию дляваша система, которая также доступна как localeEncoding.(Примечание GHC: в Windows в настоящее время мы не поддерживаем двухбайтовые кодировки; если кодовая страница консоли не поддерживается, то localeEncoding будет иметь значение latin1.)

Ошибки кодирования и декодирования всегда обнаруживаются и сообщаются, за исключением случаев, когдаленивый ввод / вывод (hGetContents, getContents и readFile), где ошибка декодирования просто приводит к прекращению потока символов, как с другими ошибками ввода / вывода.

Возможно, это как-то связано ствоя проблема?Если GHC по умолчанию где-то отличался от utf-8, или ваш дескриптор был настроен на использование другой кодировки, это может объяснить проблему.Если вы просто пытаетесь отобразить текст на консоли, то, возможно, происходит какая-то забавность кодовой страницы консоли.Я знаю, что у меня были подобные проблемы в прошлом с другими языками, такими как Python и печать юникода в консоли Windows.

Попробуйте запустить hSetEncoding handle utf8 и посмотрите, решит ли это вашу проблему.

...