在Haskell中处理字符串编码的正确方式是什么?

4
我使用Windows,编码为949。Excel和Notepad.exe可以保存编码为cp949的文件,但在Python中处理这些文件很容易,只需使用str.encode和str.decode即可。
最近我发现了Haskell,似乎有多种方法可以操作字符串。《Real World Haskell》告诉我要使用ByteString进行高效的IO,但我不知道如何在不同编码之间切换。
我必须读取不是UTF8编码的文件,并将它们以原始编码写回去,其中大部分将是cp949。
我的Haskell源代码内部将使用utf8编码。
在Python中,使用str进行IO,unicode进行处理原理很简单,但在Haskell中,甚至缺少内置的cp949支持。
因此,问题是:如何在各种编码下进行文件IO?我必须读取、转换、处理和写入它们。

编辑:

我尝试了两个选项,但是在Windows上的文本转换状态很糟糕。

text-icu

优点:

  • text 似乎是现代化、高级的文本操作选择
  • 在Windows上易于安装:只需获取 icu二进制文件并在使用cabal install安装text-icu时指定includelib文件夹即可。

缺点:

  • 转换器是IO
  • 无法多次初始化转换器(与线程安全有关,会出现运行时错误)
  • 不适用于Lazy bytestrings
  • 需要>20MB的dlls

iconv

优点:

  • 没有单子

缺点:

  • 在Windows上安装很麻烦
  • 尝试处理大文件时存在一些解码失败的情况..通常对于iconv(命令行或DLL),您必须提供无缓冲输入以获得正确的输出,但Haskell的绑定似乎只能使用lazy bytestrings。

1
我不知道Haskell中是否有cp949编码,但每当你需要处理文本编码时,通常最好使用text包而不是bytestring - Danny Navarro
2个回答

4
您可以使用 text-icu 包的 Convert 模块 来处理 text 不支持的编码。

假设您已经获得了编码后的 ByteString,您需要执行以下操作:

import qualified Data.Text.ICU.Convert as Convert

decodeCP949 :: ByteString -> IO Text
decodeCP949 bs = do
    conv <- Convert.open "cp949" Nothing
    return $ Convert.toUnicode conv bs

encodeCP949 :: Text -> IO ByteString
encodeCP949 t = do
    conv <- Convert.open "cp949" Nothing
    return $ Convert.fromUnicode conv t

这里的IO有点让人烦恼。我认为这是一种使用unsafePerfomIO仅获取转换器一次就可以的情况。


4
你可以在iconv包中使用Codec.Text.IConv模块:

http://hackage.haskell.org/package/iconv-0.4.1.2/docs/Codec-Text-IConv.html

< p > convert 函数将从一种编码转换为另一种编码,因此您可以将 CP949 ByteString 转换为 UTF8 ByteString(然后转换为 Text 如果需要)。< /p> < p > 您还可以反向进行此过程(Text -> UTF8 ByteString -> CP949 ByteString)< /p> < p > 这是我在 github 上找到的一些示例代码:< /p>

https://github.com/wookay/da/blob/master/haskell/fun/test_encode.hs


我不知道那个包。当你只需要快速的编码转换时,它非常方便。 - Danny Navarro

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