2012-01-08 55 views
1

我有一个Java属性文本文件,其中包含键值对。将这些数据加载到haskell然后访问它的一些好方法是什么?将属性文件加载到地图结构中

文件看喜欢:

XXXX=vvvvv 
YYYY=uuuuu 

我希望能够进入 “XXXX” 键。

回答

1

探索一些细节ehird没有提及,而稍微不同的方法:

import qualified Data.Map as Map 

type Key = String 
type Val = String 

main = do 
    -- get contents of file (contents :: String) 
    contents <- readFile "config.txt" 

    -- split into lines (optionList :: [String]) 
    let optionList = lines contents 

    -- parse into map (optionMap :: Map Key Val) 
    let optionMap = optionMapFromList optionList 

    doStuffWith optionMap 

optionMapFromList :: [String] -> Map.Map Key Val 
optionMapFromList = foldr step Map.empty 
    where step line map = case parseOpt line of 
      Just (key, val) -> Map.insert key val map 
      Nothing   -> map 

parseOpt :: String -> Maybe (Key, Val) 
parseOpt = undefined 

我已经表达了我的问题的解决方案作为一个:取文件中的行列表,并将其变成所需的地图。折叠中的每个step涉及检查单行,尝试将其解析为键/值对,并在成功时将其插入地图中。

我离开了parseOpt undefined;你可以使用像ehird的parseField或任何你喜欢的方法。也许你宁愿只分析特定的选项:

interestingOpts = ["XXXX", "YYYY"] 

parseOpt line = case find (`isPrefixOf` line) interestingOpts of 
    Just key -> Just (key, drop 1 $ dropWhile (/= '=') line) 
    Nothing -> Nothing 

使用前缀测试方法并不总是最好的主意,不过,如果您有(例如)选项“XX”和选项“XXXX” 。仔细观察,看看最适合您的数据的方法。如果您需要需要高性能,请使用Data.Text而不是String s。

+1

对于一个非常非常长的选项列表,foldr可能会打击堆栈。用foldl重写会防止这种情况发生。 – 2012-01-08 23:51:57

4

你可以使用像优秀Parsec(Haskell平台的一部分)的解析器库。编写一个简单的格式解析器只需要几分钟。

但是,如果真的那么简单,您可以使用split;使用标准lines函数将字符串拆分为多行(如果需要处理空行等,则使用Data.List.Split),然后使用Data.List.Split函数将其拆分为'='

最简单的解决办法是滚动自己与break

import Control.Arrow 

parse :: String -> [(String, String)] 
parse = map parseField . lines 
    where parseField = second (drop 1) . break (== '=') 

然而,这不处理的空白,空白行,或类似的东西。

至于通过键查找,一旦你有一个结构是怎样的[(String, String)],可以很容易地把它变成一个Map(与fromList),并在该操作。