我想从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
答案 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