从文件中读取内容并将其置于数据类型下

时间:2010-11-12 13:37:18

标签: parsing haskell file-io io

我有一个包含此文件的文件:

(Float,Float,Float)"sometext"
(Float,Float,Float)"sometext"
(Float,Float,Float)"sometext"
...
...

我希望我的程序从文件中读取一行,将(Float,Float,Float)放入一个tripple,将“sometext”放入一个String中,并将所有内容放在一个新的数据类型下,这样整个事情就会看起来像这样:

SomeDataType(Float,Float,Float)“sometext”

到目前为止我得到了这个:

readFromDisc filePath = do 
                        fileHandle <- openFile "/tmp/lala.txt" ReadMode
                        contents <- hGetContents fileHandle
                        putStrLn $ readOneLine contents

如果文件包含:

(5.0,6.0,7.0)"faraway"
(8.0,9.0,0.0)"holdon"

我明白了:

"(5.0,6.0,7.0)\"faraway\""

现在,因为我把它作为一个字符串,我正在考虑使用

breakInput input = break (=='"') input

要得到这个:

("(5.0,6.0,7.0)","\"faraway\"")

这是一对字符串,我打算使用一些东西来解析tripple和文本,但所有这些都感觉不对。

有更好的方法吗?

3 个答案:

答案 0 :(得分:6)

使用reads功能。它将解析字符串开头的匹配部分,并返回字符串的其余部分。

parseLine :: String -> [((Double, Double, Double), String)]
parseLine line = do
  (tuple, line') <- reads line
  (string, _)    <- reads line'
  return (tuple, string)

-- parseLine "(5.0, 6.0, 7.0)\"faraway\"" ---> ((5.0, 6.0, 7.0), "faraway")

这将返回匹配列表,并忽略行尾的垃圾。由于您的特定案例具有明确的解析,因此成功解析只会产生一个匹配。

答案 1 :(得分:0)

readThat (triple, str) = SomeDataType (read triple :: (Float, Float, Float)) 
                                      (read str :: String)

快速又脏。

答案 2 :(得分:0)

快速破解,如果你不关心处理错误:

data SomeDataType = SomeDataType (Float, Float, Float) String
                  deriving Read

readOneLine s = read ("SomeDataType " ++ s)