3

我意识到我的文本中的口音会被转换为�。我将其归结为以下示例,该示例写入(并覆盖)文件 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 中使用重音符号并将它们正确写入文件?

4

1 回答 1

7

这与 无关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 并不是那么最新。不过,应该可以在任何编辑器中手动选择编码。

实际上,Data.Text.IO.writeFile将使用您的语言环境来决定如何对文件进行编码。现在每个人都应该将 UTF-8作为他们的语言环境,如果你不这样做,请改变它。

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

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

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

当您对字符串类型(即 或 )使用直接 IO 输出操作时,这种转义永远putChar不会putStr发生putStrLn

Prelude> import qualified Data.Text.IO as Txt
Prelude Txt> Txt.putStrLn "Université"
Université
于 2017-08-27T12:40:40.537 回答