2012-02-10 19 views
7

Tôi muốn lấy năm byte đầu tiên từ tập tin nắm tay trong kho lưu trữ zip. Tôi sử dụng gói zip-archive để giải nén:Làm thế nào để có lười biếng bytestring từ kho lưu trữ zip mà không có đống tràn

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 

Mã này hoạt động cho lưu trữ nhỏ nhưng tôi bị tràn bộ nhớ lớn. Ví dụ:

./zip-arch test.zip +RTS -p -hy -M100M 

cho archive này cho phép này heap profile

+0

Hồ sơ heap này hiển thị mức sử dụng đống 130k, đó không phải là dấu hiệu của sự cố. Tôi sẽ tự xem. –

+0

@DanielFischer lạ, nhưng tôi đã nhận được thông báo lỗi này: Heap cạn kiệt; Kích thước heap tối đa hiện tại là 104857600 byte (100 MB); sử dụng '+ RTS -M ' để tăng nó. – tymmym

+0

@tymmym: 'fromEntry' sử dụng CRC32 checksum từ gói" digest ". nó crc32 bằng cách gọi crc32 trong zlib.h, điều này có thể tiêu thụ một số bộ nhớ? Tôi không chắc. – Nybble

Trả lời

1

Tôi đã đọc các explanation của tác giả zip-archive và quyết định để sửa chữa khuyến khích. Tôi đã hoàn thành với một thư viện mới - zip-conduit. Tính năng chính của nó là sử dụng bộ nhớ liên tục mà không cần IO lười biếng. Để lấy năm byte đầu tiên từ tệp nắm tay trong kho lưu trữ zip, bạn có thể viết:

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 
1

xem xét gọi ra unzip. Nó không phải là siêu haskelly nhưng nó thực hiện công việc. Có lẽ tất cả những kẻ thù ghét không nên dành nhiều thời gian sửa chữa hoặc thay thế các thư viện bị hỏng như zip-archive và ít thời gian hơn trên stackoverflow.

Tuyên bố từ chối trách nhiệm chuẩn: không kiểm tra lỗi hiện tại. điều này có thể bị rò rỉ xử lý. lười biếng i/o là lười biếng.

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 

Dường như làm việc:

$ runghc -Wall unzip.hs ~/Downloads/test.zip 
Chunk ",+\227F\149" Empty 
Các vấn đề liên quan