Utf8 и перегруженные строки в Haskell

Я понял, что акценты в моих текстах конвертируются в. Я свел его к следующему примеру, который записывает (и перезаписывает) файл test.txt.

Он использует исключительно методы из Data.Text, которые должны обрабатывать тексты Unicode. Я проверил, что и исходный файл, и выходной файл закодированы в utf8.

{-# LANGUAGE OverloadedStrings #-}

import Prelude hiding (writeFile)
import Data.Text
import Data.Text.IO

someText :: Text
someText = "Université"

main :: IO ()
main = do 
    writeFile "test.txt" someText

После запуска кода test.txt содержит: Universit. В ghci я получаю следующее

*Main> someText
"Universit\233"

Это уже неправильно закодировано? Я также нашел комментарий к в https://hackage.haskell.org/package/text-1.2.2.2/docs/Data-Text.html, но я все еще не знаю, как исправить приведенный выше пример.

Как использовать акценты в OverloadedString и правильно записать их в файл?

1 ответ

Решение

Это не имеет ничего общего с Data.Text и, конечно, не с OverloadedStrings - оба отлично справляются с UTF-8–Unicode.

тем не мение Data.Text.IO не будет писать спецификацию или что-либо, что указывает на кодировку, то есть файл на самом деле просто содержит текст как есть. В любой современной системе это означает, что она будет в необработанном виде UTF-8:

sagemuej@sagemuej-X302LA:~$ xxd test.txt 
00000000: 556e 6976 6572 7369 74c3 a9              Universit..
sagemuej@sagemuej-X302LA:~$ cat test.txt 
Université

Поэтому в зависимости от того, каким редактором вы открываете файл, он может угадать неправильную кодировку, и это, очевидно, ваша проблема. В Linux UTF-8 уже давно является стандартом, поэтому здесь нет проблем, но Windows не так уж и актуальна. Однако должна быть возможность вручную выбрать кодировку в любом редакторе.

По факту, Data.Text.IO.writeFile будет использовать вашу локаль, чтобы решить, как кодировать файл. У каждого должен быть UTF-8 в качестве локали в наши дни, если вы не измените его.

Чтобы получить спецификацию в своем файле и таким образом исключить такие проблемы, используйте utf8_bom,

Что касается вывода, который вы видите в GHCi: это Show экземпляр на работе; он экранирует любые строковые значения в максимально безопасную форму, т. е. все, что не является ASCII, в escape-последовательность, которая для 'é' бывает '\233', Опять не характерно для Text фактически вы получаете это даже для отдельных символов:

Prelude> 'é'
'\233'
Prelude> putChar '\233'
é

Это экранирование никогда не происходит, когда вы используете действия прямого ввода-вывода для ваших строковых типов, т.е. putChar, putStr или же putStrLn,

Prelude> import qualified Data.Text.IO as Txt
Prelude Txt> Txt.putStrLn "Université"
Université
Другие вопросы по тегам