【问题标题】:Is there no way to handle encoding with Data.Text.IO.hGetContents?有没有办法用 Data.Text.IO.hGetContents 处理编码?
【发布时间】:2016-01-22 05:54:27
【问题描述】:

当我尝试将 UTF8 文本文件读取为 Text 时,我尝试使用 Data.Text.IO.readFile
但是,当系统环境的语言环境不是*.UTF8(尤其是c)时,它就不起作用了。
它说hGetContents: invalid argument (invalid byte sequence)

是的,我阅读了文档 Data.Text.IO 中的语言环境支持部分。 它说Data.Text.IO取决于系统环境的设置。

因此,我尝试将Data.Text.IO.hGetContents 函数与System.IO.hSetEncoding h System.IO.utf8_bom 一起使用。
当我将它与System.IO.hGetContents 一起使用时,这很有效。

但是,Data.Text.IO.hGetContents 表示 text: <stdout>: commitAndReleaseBuffer: invalid argument (invalid character)

有没有办法在不改变系统环境变量(例如LANG)的情况下处理Data.Text.IO.hGetContentsData.Text.IO.readFile 的编码? 首选只编辑 Haskell 代码的方法。

这是我的原始代码:

import qualified Data.Text as T
import qualified Data.Text.IO as T

main = do
  text <- T.readFile "./data.md"
  T.putStrLn text

这是我的试用代码:

import qualified Data.Text as T
import qualified Data.Text.IO as T

import System.IO

main = do
  h <- System.IO.openFile "./data.md" System.IO.ReadMode
  System.IO.hSetEncoding h System.IO.utf8_bom
  text <- T.hGetContents h -- `System.IO.hGetContents h` works!
  T.putStrLn text

当系统的区域设置为 *.UTF8 时,这些方法有效,而在其他环境中失败。

测试环境信息:

  • Linux (Ubuntu 14.04)
  • GHC 7.10.3
  • text1.2.2.0

【问题讨论】:

  • 对于任何需要在data.md 中随机非ASCII 来测试这个的人:äüöÄÜÖßáéúíóð¾‹èɵ€†¤r’

标签: haskell text encoding utf-8


【解决方案1】:

我遇到了一些不同的错误:

<stdout>: hPutChar: invalid argument (invalid character)

即使使用System.IO.hGetContents,我也会遇到同样的错误。不知道为什么你的行为不同。 (我正在使用ghc-7.10.2text-1.2.1.3

回答问题:您正尝试将UTF-8 编码的字符串发送到stdout,配置为ASCII。我不确定它应该输出什么。

如果您的终端确实接受UTF-8,那么您可以配置stdout 忽略当前语言环境并接受UTF-8

main = do
  h <- System.IO.openFile "./data.md" System.IO.ReadMode
  System.IO.hSetEncoding h System.IO.utf8_bom
  text <- T.hGetContents h
  System.IO.hSetEncoding stdout System.IO.utf8_bom
  T.hPutStrLn stdout text

【讨论】:

  • 谢谢,它对我有用。我认为我的环境接受UTF-8stdout。我测试了这个示例代码,通过 upstart 部署了一个 Linux 服务。
【解决方案2】:

执行此操作的正确方法是使用bytestring 读取文件并使用text-icu 进行{en,de}编码。 (text 文档中提到了这一点:“要使用扩展且非常丰富的函数系列来处理 Unicode 文本...,请参阅 text-icu 包”。)例如,以下 Haskell 文件读取我的使用LANG=en_US.utf8LANG=C 正确测试文件:

import qualified Data.ByteString as BS
import qualified Data.Text.ICU.Convert as ICU

import System.IO

main = do
    -- dunno what the Nothing argument is for, read the docs!
    conv <- ICU.open "utf-8" Nothing
    h    <- openFile "test.txt" System.IO.ReadMode
    bs   <- BS.hGetContents h
    print (ICU.toUnicode conv bs)

注意我调用了print 而不是T.putStrLn——因为我的终端的输出将取决于语言环境!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-18
    • 1970-01-01
    • 2011-04-16
    • 2017-01-09
    • 2013-10-13
    • 1970-01-01
    相关资源
    最近更新 更多