慕盖茨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) }}