Haskell 中的 Utf8 和重载字符串

Utf8 and overloaded strings in 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
"Universit3"

这已经编码错误了吗?我还在 � 中找到了一条评论 https://hackage.haskell.org/package/text-1.2.2.2/docs/Data-Text.html, 但我仍然不知道如何更正上面的例子。

如何在 OverloadedString 中使用重音符号并将它们正确写入文件?

这与 Data.Text 无关,当然与 OverloadedStrings 无关 – 两者都可以很好地处理 UTF-8–Unicode。

但是 Data.Text.IO 不会写入 BOM 或任何指示编码的内容,即文件实际上只包含原样的文本。在任何现代系统上,这意味着它将采用原始 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 不是最新的。不过,应该可以在任何编辑器中手动 select 编码。

事实上,Data.Text.IO.writeFile 现在将使用您的 locale to decide how to encode the file. Everybody should have UTF-8 作为他们的语言环境,如果您不这样做,请更改它。

要在您的文件中获取 BOM,从而排除此类问题,请使用 utf8_bom

关于您在 GHCi 中看到的输出:那是正在工作的 Show 实例;它将任何类似字符串的值转义为最安全的形式,即任何不是 ASCII 的转义序列,'é' 恰好是 '3'。再次不特定于 Text,事实上,即使是单个字符,你也会得到这个:

Prelude> 'é'
'3'
Prelude> putChar '3'
é

当您对字符串类型使用直接 IO 输出操作时,这种转义永远不会发生,即 putCharputStrputStrLn.

Prelude> import qualified Data.Text.IO as Txt
Prelude Txt> Txt.putStrLn "Université"
Université