麻烦与文本编码

Pet*_*ter 3 haskell

我在文本编码方面遇到了一些麻烦.解析一个网站给我一个Data.Text字符串

"项目 - Fran\195\167ois Dubois",

我需要写一个文件.所以我使用Data.Text.Lazy.Encoding.encodeUtf8将其转换为Bytestring.问题是这会产生乱码输出:

"项目 - FrançoisDubois".

我在这里错过了什么?

Dan*_*her 5

如果你已经Fran\195\167ois进入你的内部Data.Text,你已经有了UTF-8编码François.

这是不方便的,因为Data.Text[.Lazy]应该是UTF-16编码的文本,并且两个代码单元195和167被解释为unicode代码点195.167是'Ã'.'§'.如果UTF-8编码的文本中,这些被转换为字节序列c383 ([195,131])RESP c2a7 ([194,167]).

进入这种情况的最可能方式是,您从网站获得的数据是UTF-8编码,但被解释为ISO-8859-1(拉丁语1)编码(或另一种8位编码; 8859-15是也很普遍).

处理它的正确方法是完全避免这种情况[不幸的是,这可能是不可能的].

如果您的数据源正确地表明其编码 - 如网站应该 - 找出编码并相应地解释数据.如果声明了不正确的编码,那么你当然不走运,如果没有指定编码,你必须猜对了(现在的自然猜测是UTF-8,至少对于使用拉丁字母变体的语言而言).


如果无法避免这种情况,最简单的解决方法就是

  1. 在编码之前用所需的序列替换违规序列的出现:

    encodeUtf8 $ replace (pack "Fran\195\167ois") (pack "Fran\231ois") contents
    
    Run Code Online (Sandbox Code Playgroud)
  2. 假设其他所有内容都是ASCII或无意的UTF-8,请将Text代码单元解释为字节:

    Data.ByteString.Lazy.Char8.pack $ Data.Text.Lazy.unpack contents
    
    Run Code Online (Sandbox Code Playgroud)

前者更有效,但如果存在许多不同的错误编码(例如由不同的重音字母引起)则变得不方便.后者仅在假定情况下工作(没有高于255的代码单元Text),并且对于长文本而言效率相当低.