dan*_*neu 12
这是使用 Go 的内置递归文件遍历器的解决方案,因为到目前为止最佳答案已经实现了它们自己的文件遍历器:
另外,我今天在生成 zip 文件时发现的一些发现可能会让其他人头疼:
w.Create(zippath)
不应以“/”开头,而应相对于 zip 根目录(也就是解压缩存档时创建的文件夹)。所以顶级“manifest.xml”文件应该是w.Create("manifest.xml")
. 嵌套文件应该是w.Create("a/b/c.css)
. 如果您正在生成不良/令人惊讶的档案,请先检查以确保您没有违反此规则。我的代码不会尝试强制执行此操作。filepath.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)
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
要手动执行此操作,您可以修改上面链接的代码:
举一个简单的例子,它有很多缺陷,但可能很容易理解:
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)
}
}
Run Code Online (Sandbox Code Playgroud)
我们使用它来递归地遍历文件以生成文件夹:
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() + "/")
}
}
}
Run Code Online (Sandbox Code Playgroud)