簡體   English   中英

Haskell:懶惰地用二進制文件讀取二進制文件

[英]Haskell: Lazily read binary file with binary

我正在嘗試讀取二進制文件並使用'binary'包來懶散地解析它。 包文檔提供了一個如何執行此操作的示例,而不強制與我非常類似的場景的所有輸入:

 example2 :: BL.ByteString -> [Trade]
 example2 input
  | BL.null input = []
  | otherwise =
    let (trade, rest, _) = runGetState getTrade input 0
    in trade : example2 rest

但是,這使用了已棄用的runGetState函數,該函數本身指向runGetIncremental函數。

問題是'runGetIncremental'函數似乎強制剩下的輸入是嚴格的字節串,因此強制它將整個文件加載到內存中。 實際上,當我嘗試運行時,我看到內存使用量約為6GB。 現在,即使runGetState的實現似乎也基於runGetIncremental ,然后使用chunk將strict字符串重新轉換回惰性字符串。

我可以獲得教程中描述的行為,還是二進制文件現在不支持? 如果是后者,那么最好的方法是什么? 我有一點使用管道的經驗,但我不清楚如何在這里使用它。

您可以使用pipes-binarypipes-bytestring來完成此操作。 這是一個幫助您的好處的助手功能:

import Control.Monad (void)
import Data.Binary
import Pipes
import Pipes.Binary (decodeMany)
import Pipes.ByteString (fromHandle)
import qualified Pipes.Prelude as P
import System.IO

decodeHandle :: (Binary a) => Handle -> Producer a IO ()
decodeHandle handle = void $ decodeMany (fromHandle handle) >-> P.map snd

voidmap snd在那里,因為decodeMany實際上返回更多信息(如字節偏移和解析錯誤)。 如果您確實需要該信息,那么只需刪除它們即可。

下面是一個如何使用decodeHandle ,使用快速骨架進行Trade I匯總:

data Trade = Trade

instance Binary Trade where
    get   = return Trade
    put _ = return ()

instance Show Trade where show _ = "Trade"

main = withFile "inFile.txt" ReadMode $ \handle -> runEffect $
    for (decodeHandle handle) $ \trade -> do
        lift $ print (trade :: Trade)
        -- do more with the parsed trade

您可以使用for循環解碼的交易並處理它們,或者如果您願意,可以使用管道組合:

main = withFile "inFile.txt" ReadMode $ \handle -> runEffect $
    decodeHandle handle >-> P.print

這將是懶惰的,只能解碼您實際需要的交易數量。 因此,如果您在解碼器和打印機之間插入一個take器,它將只讀取所需的輸入以處理所請求的交易數量:

main = withFile "inFile.txt" ReadMode $ \handle -> runEffect $
    for (decodeHandle handle >-> P.take 4) $ \trade -> do
        ... -- This will only process the first 4 trades

-- or using purely pipe composition:

main = withFile "inFile.txt" ReadMode $ \handle -> runEffect $
    decodeHandle handle >-> P.take 4 >-> P.print

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM