Xml 读取和关闭Haskell中的文件
我是Haskell的初学者,目前正在尝试解析xml文件列表 要从给定的文件名解析xml文件,我使用以下函数Xml 读取和关闭Haskell中的文件,xml,haskell,file-io,Xml,Haskell,File Io,我是Haskell的初学者,目前正在尝试解析xml文件列表 要从给定的文件名解析xml文件,我使用以下函数 searchXML :: String -> IO News searchXML file = do rsp <- readFile file let tags = parseTags rsp return News { author = get_val "createdBy" tags, headline =
searchXML :: String -> IO News
searchXML file = do
rsp <- readFile file
let tags = parseTags rsp
return News { author = get_val "createdBy" tags,
headline = get_val "headline" tags,
content = get_val "text" tags}
where
extr a b c = drop 1 $ takeWhile (~/= TagClose a) $
dropWhile (~/= TagOpen a b) c
get a b = extr "value" [] $ extr "property" [("name",a)] b
get_val a b = fromTagText $ (get a b) !! 0
searchXML::String->IO新闻
searchXML文件=do
新闻组
searchForKW关键字=do
xmlList takeExtension p==“.xml”)”
xml新闻->Bool
kwInNews关键字(新闻{author=a,headline=b,content=c})=isInfixOf关键字c
但是,这会导致openFile:资源耗尽(打开的文件太多)
错误。所以我认为这些文件是打开阅读的,而不是关闭的。我怎样才能解决这个问题
PS:任何进一步的重构提示都是非常受欢迎的。readFile函数就是因为这个而臭名昭著的。它假装将整个文件读入一个巨大的字符串,但实际上并没有。只需打开文件进行读取并立即返回即可。只有在以下任一情况下,文件才会关闭:
- 程序检查字符串的最后一个字符
- 程序会删除对结果的所有引用,垃圾回收器就会运行
readFile
非常适合快速检查一些小示例是否按照您的预期工作。只要您想要控制文件的打开/关闭时间,或者想要高性能(即处理大型XML文件),您就需要避免readFile
如果您知道文件很小/性能不重要,您可以手动
openFile
、hGetLine
和hClose
。这样,您就可以确切地知道文件何时关闭,因为您正在关闭它。您可能还想看看ByteString库;有一个类似于readFile
的函数,它返回一个严格的ByteString(换句话说,它实际上一次加载整个文件)。ByteString
类型也比String
类型有效得多(但使用起来更灵活)。根据@MathematicalOrchid的建议,我正在使用readFile
from Data.ByteString和Data.ByteString.Char8.unpack
函数将ByteString转换为字符串
import qualified Data.ByteString as Str
import qualified Data.ByteString.Char8 as Char8
searchXML :: String -> IO News
searchXML file = do
rsp <- Str.readFile file
let get a = getVal a $ parseTags $ Char8.unpack rsp
auth = get "createdBy"
headl = get "headline"
cont = get "text"
return News {author = auth, headline = headl, content = cont}
where
extract tag attr = (drop 1) . (takeWhile (~/= TagClose tag))
. dropWhile (~/= TagOpen tag attr)
getVal attr = (fromTagText . safeHead . extract "value" [])
. extract "property" [("name", attr)]
safeHead (x:xs) = x
safeHead [] = TagText " "
导入符合条件的数据.ByteString作为Str
将限定的Data.ByteString.Char8导入为Char8
searchXML::String->IO新闻
searchXML文件=do
rsp问题是您读取文件时比较懒惰-最好使用类似于为什么要将其转换为字符串
<事实证明,code>String
几乎总是错误的。如果您使用{-#OverloadedStrings#-}
您可以使用ByteString
文本,ByteString
提供了许多不同的stringy操作供您使用来处理它们。但是对于XML,有一些包可以正确地做到这一点。
import qualified Data.ByteString as Str
import qualified Data.ByteString.Char8 as Char8
searchXML :: String -> IO News
searchXML file = do
rsp <- Str.readFile file
let get a = getVal a $ parseTags $ Char8.unpack rsp
auth = get "createdBy"
headl = get "headline"
cont = get "text"
return News {author = auth, headline = headl, content = cont}
where
extract tag attr = (drop 1) . (takeWhile (~/= TagClose tag))
. dropWhile (~/= TagOpen tag attr)
getVal attr = (fromTagText . safeHead . extract "value" [])
. extract "property" [("name", attr)]
safeHead (x:xs) = x
safeHead [] = TagText " "