猿问

如何在 Golang 中压缩包含子目录或文件的目录?

我知道这与zip 包有关,我只是不知道如何实现这样的事情。


慕村9548890
浏览 270回答 2
2回答

慕盖茨4494581

要手动执行此操作,您可以修改上面链接的代码:ExampleZipWriter给你一个简单的例子,它有很多缺陷,但可能很容易理解:func ZipWriter() {    baseFolder := "/Users/tom/Desktop/testing/"    // Get a Buffer to Write To    outFile, err := os.Create(`/Users/tom/Desktop/zip.zip`)    if err != nil {        fmt.Println(err)    }    defer outFile.Close()    // Create a new zip archive.    w := zip.NewWriter(outFile)    // Add some files to the archive.    addFiles(w, baseFolder, "")    if err != nil {        fmt.Println(err)    }    // Make sure to check the error on Close.    err = w.Close()    if err != nil {        fmt.Println(err)    }}我们也使用它来递归地迭代文件以生成文件夹:func addFiles(w *zip.Writer, basePath, baseInZip string) {    // Open the Directory    files, err := ioutil.ReadDir(basePath)    if err != nil {        fmt.Println(err)    }    for _, file := range files {        fmt.Println(basePath + file.Name())        if !file.IsDir() {            dat, err := ioutil.ReadFile(basePath + file.Name())            if err != nil {                fmt.Println(err)            }            // Add some files to the archive.            f, err := w.Create(baseInZip + file.Name())            if err != nil {                fmt.Println(err)            }            _, err = f.Write(dat)            if err != nil {                fmt.Println(err)            }        } else if file.IsDir() {            // Recurse            newBase := basePath + file.Name() + "/"            fmt.Println("Recursing and Adding SubDir: " + file.Name())            fmt.Println("Recursing and Adding SubDir: " + newBase)            addFiles(w, newBase, baseInZip  + file.Name() + "/")        }    }}

慕哥6287543

这是使用 Go 的内置递归文件遍历器的解决方案,因为到目前为止的最佳答案已经实现了他们自己的文件遍历器:除此之外,我今天在生成 zip 文件时发现的一些发现可能会让其他人头疼:to 的参数不w.Create(zippath)应该以“/”开头,并且应该相对于 zip 根目录(也就是解压缩存档时创建的文件夹)。所以一个顶级的“manifest.xml”文件应该是w.Create("manifest.xml"). 嵌套文件应该是w.Create("a/b/c.css). 如果您正在生成不良/令人惊讶的档案,请先检查以确保您没有违反此规则。我的代码不会尝试强制执行此操作。一些规范(如 epub)希望文件按特定顺序排列,但 Gofilepath.Walk会按词汇顺序爬行。(就此而言,我发现到目前为止,从 Calibre 到 macOS 上的 Books.app,所有 epub 解析器都很宽松)。如果您需要特定的顺序,那么@LeTigre 的解决方案ReadDir可以让您在每个下降级别对文件进行排序。package mainimport (    "archive/zip"    "fmt"    "io"    "os"    "path/filepath")// Zips "./input" into "./output.zip"func main() {    file, err := os.Create("output.zip")    if err != nil {        panic(err)    }    defer file.Close()    w := zip.NewWriter(file)    defer w.Close()    walker := func(path string, info os.FileInfo, err error) error {        fmt.Printf("Crawling: %#v\n", path)        if err != nil {            return err        }        if info.IsDir() {            return nil        }        file, err := os.Open(path)        if err != nil {            return err        }        defer file.Close()        // Ensure that `path` is not absolute; it should not start with "/".        // This snippet happens to work because I don't use         // absolute paths, but ensure your real-world code         // transforms path into a zip-root relative path.        f, err := w.Create(path)        if err != nil {            return err        }        _, err = io.Copy(f, file)        if err != nil {            return err        }        return nil    }    err = filepath.Walk("input", walker)    if err != nil {        panic(err)    }}
随时随地看视频慕课网APP

相关分类

Go
我要回答