我正在尝试使用Haskell中的cassava/Data.Csv解析制表符分隔的文件.但是,如果我的CSV文件中存在"奇怪的"(Unicode)字符,则会出现问题.我会得到一个parse error (endOfInput).
根据命令行工具"文件",我的文件有一个"UTF-8 Unicode文本"解码.我的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
Run Code Online (Sandbox Code Playgroud)
我尝试使用decodeUtf8 ',使用Data.Char中的谓词预处理(过滤)输入等等.但是endOfFile错误仍然存在.
我的CSV文件如下所示:
a - - - RT USE " Kenny" • Hahahahahahahahaha. #Emmen #Brandstapel
a - - - Uhm .. wat dan ook ????!!!!
Run Code Online (Sandbox Code Playgroud)
或者更确切地说:
a\t-\t-\t-\tRT USE " Kenny" • Hahahahahahahahaha. #Emmen #Brandstapel
a\t-\t-\t-\tUhm .. wat dan ook ????!!!!
Run Code Online (Sandbox Code Playgroud)
问题字符是和•(在我的完整文件中,还有更多相似的字符).我该怎么办,以便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
Run Code Online (Sandbox Code Playgroud)
根据木薯文档:
\n\n\n\n\n\n
\n- \n
非转义字段可以包含除双引号、逗号、回车符和换行符之外的任何字符。
- \n
转义字段可以包含任何字符(但双引号需要转义)。
由于第一个记录中的最后一个字段包含双引号,因此该字段需要用双引号转义,并且任何双引号都需要转义,如下所示:
\n\na - - - "RT USE "" Kenny"" \xe2\x80\xa2 Hahahahahahahahaha. #Emmen #Brandstapel"\nRun Code Online (Sandbox Code Playgroud)\n\n这段代码对我有用:
\n\nimport Data.ByteString.Lazy\nimport Data.Char\nimport Data.Csv\nimport Data.Text.Encoding\nimport Data.Vector\n\ntest :: Either String (Vector (String, String, String, String, String))\ntest = decodeWith\n defaultDecodeOptions {decDelimiter = fromIntegral $ ord \'\\t\' }\n NoHeader\n (fromStrict $ encodeUtf8 "a\\t-\\t-\\t-\\t\\"RT USE \\"\\" Kenny\\"\\" \xe2\x80\xa2 Hahahahahahahahaha. #Emmen #Brandstapel\\"")\nRun Code Online (Sandbox Code Playgroud)\n\n(请注意,我必须确保使用encodeUtf8类型的文字Text,而不是ByteString直接使用文字。 sIsString的实例ByteString,用于将文字转换为 a ByteString,会截断每个 Unicode 代码点。)
| 归档时间: |
|
| 查看次数: |
1291 次 |
| 最近记录: |