如何在FSharp中压缩文件?

时间:2010-12-28 19:08:38

标签: .net f# zip

粗略的谷歌搜索没有返回任何简单易懂的内容(我对函数式编程很陌生)。

如果我有一个文件数组,我如何压缩每个文件,然后创建所有压缩文件的zip?

到目前为止我有这样的事情:

let zip f = 
    f.zip //this is where I need the most direction

let zipAllAttachments f =
    f
    |> Seq.map zip   //do I need to create another function to create a single zip of all zips?
编辑:这是我到目前为止所做的,但我有一些奇怪的行为。一旦我弄清楚奇怪的行为究竟是什么,就会有更多的事情发生:

use zipfile = new ZipFile()
for fileObj in files do
    zipfile.AddFile(sprintf "%s%s" path  fileObj.Filename) |> ignore
    zipfile.Save("C:\\temp\\Compliance.zip")

更新:我不认为“奇怪的行为”与zip模块有关。我感谢所有的帮助!

3 个答案:

答案 0 :(得分:8)

您是否尝试创建zip压缩的独立实现?

我使用http://dotnetzip.codeplex.com/中的DotNetZip - 它是一个托管代码(C#)程序集。从F#中使用它应该与引用项目中的程序集一样简单。

用法很简单。对于C#:

using (ZipFile zip = new ZipFile())
{
  // add this map file into the "images" directory in the zip archive
  zip.AddFile("c:\\images\\personal\\7440-N49th.png", "images");
  // add the report into a different directory in the archive
  zip.AddFile("c:\\Reports\\2008-Regional-Sales-Report.pdf", "files");
  zip.AddFile("ReadMe.txt");
  zip.Save("MyZipFile.zip");
}

如果你想压缩一组zip文件(为什么?),有很多种方法可以使用DotNetZip(例如,你可以将zip文件保存到流中,或者将流添加到zip中文件)。

希望这有帮助!


编辑注: DotNetZip曾经住在Codeplex。 Codeplex已关闭。旧档案仍然[可在Codeplex] [1]获得。看起来代码已迁移到Github:


答案 1 :(得分:3)

我没有使用Nicholas提到的zip库,但这可能是你想要的F#版本。

let create_zip_file (files: seq<string>) zipfile_name = 
    use zipfile = new ZipFile()
    files
    |> Seq.iter (fun f -> zip.AddFile(f))

    zipfile.Save(zipfile_name)

如果过载,您可能还需要向zipfile_name添加类型信息。

此功能可用于创建单个文件的zip文件,然后用于创建包含所有较小zip文件的大型zip文件。这是一个例子,尽管你实际上并不想像现在这样在整个地方复制文件名。

create_zip_file ["first_file"] "first_file.zip"
create_zip_file ["second_file"] "second_file.zip"
create_zip_file ["first_file.zip"; "second_file.zip"] "big_file.zip"

答案 2 :(得分:0)

从.NET 4.6.2开始,可以使用ZipArchive类:

namespace FSharpBasics

module ZipThis =

    open System.IO
    open System.IO.Compression
    open System.Reflection
    open System

    let create (zipName: string) (files: seq<FileInfo>) =
        use s = File.Create(zipName)
        use z = new ZipArchive(s, ZipArchiveMode.Create)
        files
            |> Seq.map (fun item -> (item.FullName, item.Name))
            |> Seq.iter (fun (path, name) -> z.CreateEntryFromFile (path, name) |> ignore)

    [<EntryPoint>]
    let main argv =
        let di = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory)
        printfn "Creating test.zip on current directory"
        create "test.zip" (di.GetFiles "*.dll")
        printfn "Created"
        0