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é