使用readFile的Haskell字符编码问题

时间:2016-01-14 22:11:11

标签: haskell character-encoding

虽然我经历了一堆Haskell编码 - 问题 - 问题我无法解决以下问题:

我想阅读许多不同的文本文件;文件的字符编码可能不一致,我正在使用的任何readFile-Function都会在读取某些文件时抛出异常。

我试图压缩问题:以下情况总结了它的核心。

import Prelude hiding (writeFile, readFile)
import qualified Text.Pandoc.UTF8 as UTF (readFile, writeFile, putStr, putStrLn)
import qualified Prelude as Prel (writeFile, readFile)
import Data.ByteString.Lazy (ByteString, writeFile, readFile)

在ghci中我得到以下结果:

*Main> Prel.readFile "Test/A.txt"
*** Exception: Test/A.txt: hGetContents: invalid argument (invalid byte sequence) "\226\8364
*Main> Prel.readFile "Test/C.txt"
"\8230\n"

*Main> UTF.readFile "Test/A.txt"
"\8221\n"

*Main> UTF.readFile "Test/C.txt"
*** Exception: Cannot decode byte '\x85':      
Data.Text.Internal.Encoding.Fusion.streamUtf8: Invalid UTF-8 stream 

以下信息可能会有所帮助:

  • getLocaleEncoding收益CP1252
  • 两个"有问题的"的ByteString文本文件:

*Main> readFile "Test/A.txt" "\226\128\157\r\n" *Main> readFile "Test/C.txt" "\133\r\n"

我的问题是:我如何捕获/处理/避免这些字符编码错误?关键是:我事先不知道文本文件的编码,我需要一个适用于所有人的readFile方法。 如果不可能并且抛出异常,我希望捕获异常并继续我的程序以便能够尝试另一个readFile函数或者只是跳过该文本文件然后转到下一个。

2 个答案:

答案 0 :(得分:3)

由于所有其他答案提到的原因,这并不容易。但一切都不会丢失。使用charsetdetect - 显然是基于Mozilla算法 - 检测每个字节串的编码。然后将检测到的编码传递给text-icuencoding进行解码。检测不适用于最奇怪和最晦涩的文本编码,但其余部分应该有效。

答案 1 :(得分:2)

您想要的是不可能的,原因如下:

有许多8位编码,其中所有或大多数可能的8位模式都分配给某个字符。根本没有办法找出它是哪种编码。你绝对需要事先知道编码的是什么:一些俄语或希腊文,也许吧?或者只是德语,其中大多数字符将在7位ASCII平面中,并且偶尔会有ä或ß。

出于这个原因,聪明人发明了Unicode和UTF-8,你需要做的就是说:从今天起我会

  • 以UTF-8
  • 撰写所有文本
  • 不接受任何非UTF-8编码的文件。
  • 将取消与提供UTF-8编码文件的人的所有社交关系,但事实证明该文件以所谓的“字节顺序标记”(BOM)开头。

让那些坚持使用40年历史的专有编码成为少数人的人,即使像微软这样的巨头也会被迫放弃他们的坏习惯!