2

我正在尝试在 Haskell 中使用LibZip找出一个非常简单的任务:如何打开存档foo.zip、解压缩、重新压缩并将其保存到新存档中bar.zip?使用Zip库,这很容易:

{-# LANGUAGE OverloadedStrings #-}

import Codec.Archive.Zip (toArchive, fromArchive)
import qualified Data.ByteString.Lazy as B
import System.Environment

saveZipAs :: FilePath -> FilePath -> IO () 
saveZipAs source dest = do
    arch <- fmap toArchive $ B.readFile source
    putStrLn "Archive info: " >> print arch
    B.writeFile dest $ fromArchive arch

另一方面,LibZip 没有提供明确的方法来做到这一点(我可以看到)。它似乎只能实例化一个 zip 文件withArchive(这本身就是一个问题,因为您要打开的文件可能不在磁盘上),而且我看不到任何一种“另存为”操作,也不将压缩字节提取为 aByteString或其他方式(如在 Zip 中)。LibZip 据说比 Zip 快,所以我想至少试一试,但它似乎更加晦涩难懂(而且不纯,随身携带一个IO它所到之处,实际上只在开始和结束时才需要它,如果曾经)。谁能给我一些提示?

旁注:令人难以置信的是人们如何花费如此多的时间编写一个库,结果却如此糟糕,以至于没有人可以使用它。图书馆作者,请不要这样做!

4

1 回答 1

4

您的链接以某种方式指向该库的旧版本,并且该库的最后一个版本似乎有黑线鳕编译错误。

以下是较新版本中的文件读取功能:

http://hackage.haskell.org/package/LibZip-0.10.2/docs/Codec-Archive-LibZip.html#g:3

逆过程似乎是addFile/sourceBuffer和相关函数。

这是zip重新打包的完整源代码:

import Codec.Archive.LibZip
import Codec.Archive.LibZip.Types

main = readZip "foo.zip" >>= writeZip "bar.zip"

readZip :: FilePath -> IO [(FilePath, ZipSource)]
readZip zipName = withArchive [] zipName $ do
        nn <- fileNames []
        ss <- mapM (\n -> sourceFile n 0 (-1)) nn
        return $ zip nn ss

writeZip :: FilePath -> [(FilePath, ZipSource)] -> IO ()
writeZip zipName zipContent = withArchive [CreateFlag] zipName $ do
        mapM_ (uncurry addFile) zipContent

仍然可以进行很少的重构:liftM2 zip可以在 中使用readZip,并且.writeZip.

于 2013-10-01T07:46:01.683 回答