所以我有一个解码功能
decodeResult :: Data.ByteString.Lazy.ByteString -> Maybe Result
我从Data.Text.Lazy.IO开始将文件加载到Lazy ByteString中,
import qualifIEd Data.Text.Lazy.IO as Timport qualifIEd Data.Text.Lazy.EnCoding as TgetfileContent :: filePath -> IO B.ByteStringgetfileContent path = T.encodeUtf8 `fmap` T.readfile path
它编译了,但我遇到了太多文件打开的问题,所以我想也许我应该使用withFile.
import System.IOimport qualifIEd Data.ByteString.Lazy as Bimport qualifIEd Data.Text.Lazy.IO as Timport qualifIEd Data.Text.Lazy.EnCoding as TgetfileContent :: filePath -> IO (Maybe Result)getfileContent path = withfile path ReadMode $\hnd -> do content <- T.hGetContents hnd return $(decodeAnalytic . T.encodeUtf8) contentloadAllResults :: filePath -> IO [Result]loadAllResults path = do paths <- ListDirectory path results <- sequence $fmap getfileContent (fmap (path ++ ) $filter (endswith ".Json") paths) return $catMaybes results
在这个版本中,懒惰的io似乎永远不会被评估,它总是返回空列表.但是如果我在getfileContent函数中打印内容,那么一切似乎都能正常工作.
getfileContent :: filePath -> IO (Maybe Result)getfileContent path = withfile path ReadMode $\hnd -> do content <- T.hGetContents hnd print content return $(decodeAnalytic . T.encodeUtf8) content
所以我不确定我错过了什么,我应该使用导管来做这类事吗?
解决方法 一般来说,我建议使用流式库来解析像JsON文件这样的任意大小的数据.但是,在使用aeson解析JsON的特定情况下,超出内存的问题并不像IMO那么重要,因为aeson库本身最终将内存中的整个文件表示为Value类型.因此,您可以选择简单地使用严格的字节串I / O.我给出了一个使用管道和严格I / O来解析JsON值的示例. (我认为导管版本已存在于某些库中,我不确定.)#!/usr/bin/env stack{- stack --resolver lts-7.14 --install-ghc runghc --package aeson --package conduit-extra-}import Control.Monad.Catch (MonadThrow,throwM)import Control.Monad.IO.Class (Monadio,liftIO)import Data.Aeson (FromJsON,Result (..),eitherDecodeStrict',fromJsON,Json,Value)import Data.ByteString (ByteString)import qualifIEd Data.ByteString as Bimport Data.Conduit (ConduitM,runconduitRes,(.|))import Data.Conduit.Attoparsec (sinkParser)import Data.Conduit.Binary (sourcefile)sinkFromJsON :: (MonadThrow m,FromJsON a) => ConduitM ByteString o m asinkFromJsON = do value <- sinkParser Json case fromJsON value of Error e -> throwM $userError e Success x -> return xreadJsONfile :: (Monadio m,FromJsON a) => filePath -> m areadJsONfile fp = liftIO $runconduitRes $sourcefile fp .| sinkFromJsON-- Or using strict I/OreadJsONfileStrict :: (Monadio m,FromJsON a) => filePath -> m areadJsONfileStrict fp = liftIO $do bs <- B.readfile fp case eitherDecodeStrict' bs of left e -> throwM $userError e Right x -> return xmain :: IO ()main = do x <- readJsONfile "test.Json" y <- readJsONfileStrict "test.Json" print (x :: Value) print (y :: Value)
编辑忘记提及:我强烈建议不要使用文本I / O来读取您的JsON文件. JsON文件应使用UTF-8编码,而文本I / O函数将使用系统设置指定的任何字符编码.依靠Data.ByteString.readfile和类似的更可靠.我详细介绍了in a recent blog post.
总结以上是内存溢出为你收集整理的如何使用Data.Text.Lazy.IO用Aeson解析JSON文件全部内容,希望文章能够帮你解决如何使用Data.Text.Lazy.IO用Aeson解析JSON文件所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)