GHC中的字符编码问题

3
当我尝试在Haskell程序中读取纯文本文件时,出现以下错误信息:

[fromList * Exception: /path/to/file/aaa.txt hGetContents: invalid argument (Invalid or incomplete multibyte or wide character)

我通过谷歌搜索发现,通常将LANG设置为en_US.UTF-8即可解决此问题。我的语言环境已经是这样了。

不确定这是否与GHC有关。

我使用的是Ubuntu 11.10。

1个回答

4

您确定 aaa.txt 包含有效的 UTF-8 编码吗?如果是二进制数据,您需要使用 withBinaryFile 或类似函数。如果它是另一种编码的文本,则应该使用 hSetEncoding

例如,如果您的文本是 Latin-1 编码,则应该这样写:

hSetEncoding h latin1

这里的“h”是您的文件句柄。如果您正在从标准输入读取,则其为

hSetEncoding stdin latin1

还有一个mkTextEncoding函数,如果您已经从元数据中读取了编码,或者希望自定义处理无效的Unicode(尽管这仅在某些系统上有效),则可以使用它。

Unicode标准规定,Unicode解析器应该拒绝具有错误的字符串,并显示错误信息,而不是尝试修复它们。 这是对Postel's Law的有意拒绝,理由是减少安全漏洞和不一致的解释。

如果你需要处理大量文本并且需要处理编码问题,你可能会考虑使用text库;与使用字符串相比,它通常更快,因为它使用未装箱的数组而不是链表,尽管这意味着Text值和对它们的操作必须是严格的。它还让你更加方便地配置如何响应无效的Unicode


这些是来自古腾堡计划的纯文本文件。我刚刚检查了一下,文件中写着“字符集编码:ISO Latin-1”。如何使用hSetEncoding?我找不到一个例子。我尝试加入一行代码"hSetEncoding = "latin1"",虽然编译通过了,但仍然出现了相同的错误。 - atlantis
1
hSetEncoding h latin1,其中 h 是您的文件句柄。您有阅读过 Haskell 教程吗?不是针对您,只是这样做可以更轻松地使用标准库函数 :) - ehird
1
您可以在此处查看TextEncoding值列表(http://hackage.haskell.org/packages/archive/base/latest/doc/html/System-IO.html#t:TextEncoding);同样,也可以通过单击同一页面上hSetEncoding的类型签名中的TextEncoding链接来查看。 - ehird
在Linux下,默认的TextEncoding模式将从LANG中获取,因此文件必须是utf8编码的文件,而不是iso-8859文件。 - Jonke
@Jonke:没错,所以如果你知道编码方式的话,就应该使用hSetEncoding :) - ehird
@Paul Johnson:你确定Unicode标准是这么说的吗?我可以相信他们建议这样做,但U+FFFD REPLACEMENT CHARACTER似乎存在的目的是用它来替换被拒绝的序列。 - ehird

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接