如何在 Haskell 中确定文件文本编码而不使用 openFile 获取句柄?

问题描述 投票:0回答:1

问题是 openFile 假定 UTF-8 并且句柄返回该编码作为编码。 真正的问题是我正在获取(由学生)提交的以 UTF-16LE 编码的文件,我想要识别这些文件,因此我可以将它们转换为 UTF-8。这些文件实际上没有任何超出 ASCII 范围的内容,除了 BOM 标记(转换为 UTF-8 后会排序)。 我尝试了以下方法:

fixFileEncoding fname =
  do hdl <- openFile fname ReadMode
     menc <- hGetEncoding hdl
     hClose hdl
     case menc of
       Nothing   ->  system ("cp "++fname++" safe"++fname)
       Just enc  -> 
         do let encstr = show enc
            putStrLn ("@@@@@@" ++ fname ++ " is "++encstr)
            if take 6 encstr == "UTF-16"
            then 
              system ("iconv -f UTF-16LE -t UTF-8 "++fname++" > safe"++fname)
            else 
              system ("cp "++fname++" safe"++fname)

无论文件的实际编码如何,“@@@@@”行都会报告 UTF-8。我通过使用 unix

file
命令观察文件类型来验证这一点。

haskell text encoding utf-16 utf
1个回答
0
投票

通常您可以根据文件的生成方式了解文件的编码。有诸如 BOM 之类的临时解决方案,但它们仍然依赖于遵守这种格式的生产商。

如果没有关于编码的先验知识(学生提交的文件就是这种情况),唯一的方法是使用启发式:将二进制文件读取为字节串,使用

Data.ByteString.readFile
,尝试用一些猜测来解码它编码(
Data.Text.Encoding
包含 UTF 编码),并保留成功的编码。如果适用不止一种编码,则可能需要更多启发式方法。

为了解释您在尝试中观察到的结果,当您打开文件时,编码只是根据操作系统上的环境变量(特别是区域设置)猜测的,这就是为什么您总是使用

hGetEncoding
得到相同的结果。所有
openFile
必须继续的是文件名,这没有足够的上下文来猜测文件的编码。

© www.soinside.com 2019 - 2024. All rights reserved.