我正在尝试使用Haskell中的cassava/Data.Csv解析一个制表符分隔的文件。然而,如果我的CSV文件中有“奇怪”的(Unicode)字符,我就会遇到问题。然后我会得到一个
更直接地说:
问题字符是 & 和 •(在我的完整文件中还有许多类似的字符)。我该怎么办,才能使cassava / Data.Csv正确读取我的文件?
编辑:我已经创建了以下预处理程序,用于在使用cassava进行解码之前转义我的文本(请参见tibbe的答案)。可能有更好的可能性,但到目前为止,这个方法运作良好!
解析错误(endOfInput)
。
根据命令行工具“file”的显示结果,我的文件采用“UTF-8 Unicode text”编码格式。我的Haskell代码如下:
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE OverloadedStrings #-}
import qualified Data.ByteString as C
import qualified System.IO.UTF8 as U
import qualified Data.ByteString.UTF8 as UB
import qualified Data.ByteString.Lazy.Char8 as DL
import qualified Codec.Binary.UTF8.String as US
import qualified Data.Text.Lazy.Encoding as EL
import qualified Data.ByteString.Lazy as L
import Data.Text.Encoding as E
-- Handle CSV / TSV files with ...
import Data.Csv
import qualified Data.Vector as V
import Data.Char -- ord
csvFile :: FilePath
csvFile = "myFile.txt"
-- Set delimiter to \t (tabulator)
myOptions = defaultDecodeOptions {
decDelimiter = fromIntegral (ord '\t')
}
main :: IO ()
main = do
csvData <- L.readFile csvFile
case EL.decodeUtf8' csvData of
Left err -> print err
Right dat ->
case decodeWith myOptions NoHeader $ EL.encodeUtf8 dat of
Left err -> putStrLn err
Right v -> V.forM_ v $ \ (category :: String ,
user :: String ,
date :: String,
time :: String,
message :: String) -> do
print message
我尝试使用decodingUtf8',使用来自Data.Char的谓词对输入进行预处理(过滤),还有其他一些尝试。但是仍然存在endOfFile错误。
我的CSV文件看起来像这样:
a - - - RT USE " Kenny" • Hahahahahahahahaha. #Emmen #Brandstapel
a - - - Uhm .. wat dan ook ????!!!!
更直接地说:
a\t-\t-\t-\tRT USE " Kenny" • Hahahahahahahahaha. #Emmen #Brandstapel
a\t-\t-\t-\tUhm .. wat dan ook ????!!!!
问题字符是 & 和 •(在我的完整文件中还有许多类似的字符)。我该怎么办,才能使cassava / Data.Csv正确读取我的文件?
编辑:我已经创建了以下预处理程序,用于在使用cassava进行解码之前转义我的文本(请参见tibbe的答案)。可能有更好的可能性,但到目前为止,这个方法运作良好!
import qualified Data.Text as T
preprocess :: T.Text -> T.Text
preprocess txt = cons '\"' $ T.snoc escaped '\"'
where escaped = T.concatMap escaper txt
escaper :: Char -> T.Text
escaper c
| c == '\t' = "\"\t\""
| c == '\n' = "\"\n\""
| c == '\"' = "\"\""
| otherwise = T.singleton c