为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕村9548890 2022-01-17 18:27:22
我知道这与zip 包有关,我只是不知道如何实现这样的事情。
查看完整描述

2 回答

?
慕盖茨4494581

TA贡献1850条经验 获得超11个赞

要手动执行此操作,您可以修改上面链接的代码:


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() + "/")

        }

    }

}


查看完整回答
反对 回复 2022-01-17
?
慕哥6287543

TA贡献1831条经验 获得超10个赞

这是使用 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 main


import (

    "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)

    }

}


查看完整回答
反对 回复 2022-01-17
  • 2 回答
  • 0 关注
  • 269 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信