Как заархивировать файлы в FSharp? - PullRequest
1 голос
/ 28 декабря 2010

Краткий поиск Google не дал ничего достаточно простого для понимания (я довольно новичок в функциональном программировании).

если у меня есть массив файлов, как я могу сжать каждый файл, а затем создать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?

EDIT: это то, что у меня есть до сих пор, но у меня странное поведение.Еще больше, когда я выясню, что такое странное поведение:

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 ]

8 голосов
/ 28 декабря 2010

Вы пытаетесь создать независимую реализацию сжатия zip?

Я бы использовал DotNetZip из http://dotnetzip.codeplex.com/ - это одна сборка управляемого кода (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] [1]. Похоже, что код перенесен на Github:


3 голосов
/ 29 декабря 2010

Я не использовал 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"
0 голосов
/ 21 мая 2018

Начиная с .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
...