如何在没有堆溢出的情况下从zip存档中获取lazy bytestring

时间:2012-02-10 10:21:33

标签: haskell zip memory-leaks

我想从zip存档中的第一个文件中获取前五个字节。我使用zip-archive包进行解压缩:

import qualified Data.ByteString.Lazy as L
import Data.Maybe
import System.Environment (getArgs)

import Codec.Archive.Zip

main = do
    f:_ <- getArgs
    print . L.take 5 . fromEntry . head . zEntries . toArchive =<< L.readFile f

这段代码适用于小型档案,但我有大量的堆溢出。例如:

./zip-arch test.zip +RTS -p -hy -M100M
这个archive

给出了这个heap profile

2 个答案:

答案 0 :(得分:1)

考虑呼叫unzip。它不是超级哈斯凯利,但它完成了这项工作。也许所有那些仇恨者都应该花更多的时间来修复或替换像zip-archive这样的破坏库,而减少堆栈溢出时间。

标准免责声明:不存在错误检查。这可能会泄漏手柄。懒惰的i / o很懒。

import System.Environment (getArgs)
import System.IO (hSetBinaryMode)
import System.Process (StdStream(...), createProcess, proc, close_fds, std_out)

import qualified Data.ByteString.Lazy as L

unzipLBS :: FilePath -> IO L.ByteString
unzipLBS file = do
  let args = proc "unzip" ["-p", file]
      args' = args { std_out = CreatePipe, close_fds = True }

  (_, Just hOut, _, _) <- createProcess args'
  hSetBinaryMode hOut True
  L.hGetContents hOut

main :: IO ()
main = do
  f:_ <- getArgs
  print . L.take 5 =<< unzipLBS f

似乎工作:

$ runghc -Wall unzip.hs  ~/Downloads/test.zip
Chunk ",+\227F\149" Empty

答案 1 :(得分:1)

我已经阅读了zip-archive作者的explanation,并决定进行推荐的修复。我已经完成了一个新的库 - zip-conduit。它的主要特点是不使用懒惰IO的常量内存使用。要从zip存档中的第一个文件中获取前五个字节,您可以写:

import           System.Environment
import           Data.Conduit
import qualified Data.Conduit.Binary as CB

import           Codec.Archive.Zip

main = do
    f:_ <- getArgs
    res <- withArchive f $ do
               name:_ <- fileNames
               source <- getSource name
               runResourceT $ source $$ CB.take 5
    print res
相关问题