我使用以下代码将一些文件夹压缩到给定路径,我目前面临的问题是我需要将一些包含内容的文件夹压缩到特定目标而不是在同一目录中
例如
路径中的文件夹 来源
"/Users/i03434/go/src/zdf/BUILD"
目标
"/Users/i03434/go/src/zdf/app/info.zip"
目前我尝试添加新路径[2],但没有帮助,知道怎么做吗?
这就是全部代码
func zipit(params ...string) error {
zipfile, err := os.Create(params[1])
if err != nil {
return err
}
defer zipfile.Close()
archive := zip.NewWriter(zipfile)
defer archive.Close()
info, err := os.Stat(params[0])
if err != nil {
return err
}
var baseDir string
if info.IsDir(); len(params) > 2 {
baseDir = params[2]
} else {
baseDir = filepath.Base(params[0])
}
if baseDir != "" {
baseDir += "/"
}
filepath.Walk(params[0], func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
if baseDir != "" {
header.Name = filepath.Join(strings.TrimPrefix(path, baseDir))
}
header.Method = zip.Deflate
writer, err := archive.CreateHeader(header)
if err != nil {
return err
}
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(writer, file)
return err
})
return err
}
zip 的逻辑按预期工作,zip 应该符合 jar 规范
最佳答案
用于测试:
您可以传递一个模拟变量 zipFile
这暗示了 io.Writer
接口(interface),作为函数的参数 zipit
并将其与测试中的预期数据进行比较。
此外,您还需要目标中的一组已知文件,以便将其与模拟中的值进行比较。
Refer this for testing io.Writer
测试代码:
用特定值 source
创建的压缩文件的字符串值& newBaseDir
应该事先知道并存储在want
中.
func TestZipIt(t *testing.T) {
source := ""
newBaseDir := ""
var zipFileMock bytes.Buffer
if err := zipit(zipFileMock, source, newBaseDir); err != nil {
t.Fatalf("zipit() returned an error: %s", err)
}
got := b.String()
// want is the value of the zipped file as a string
want := ...
if got != want {
t.Errorf("zipit() test failed")
// t.Errorf("zipit() = %q, want %q", got, want)
}
}
程序代码:
func main() {
...
// params[0] is source
// params[1] is destination
// params[2] is newBaseDirectory
zipfile, err := os.Create(destination)
if err != nil {
// handle error
}
defer zipfile.Close()
if err = zipit(zipfile, source, newBaseDir); err != nil {
// handle error
}
...
}
func zipit(zipFile io.Writer, source, newBaseDir string) error {
archive := zip.NewWriter(zipfile)
defer archive.Close()
info, err := os.Stat(source)
if err != nil {
return err
}
var baseDir string
if info.IsDir() {
baseDir = filepath.Dir(source)
}
if baseDir != "" {
baseDir += "/"
}
filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
if baseDir != "" {
header.Name = filepath.Join(newBaseDir, strings.TrimPrefix(path, baseDir))
}
header.Method = zip.Deflate
writer, err := archive.CreateHeader(header)
if err != nil {
return err
}
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(writer, file)
return err
})
return err
}
原始答案:
有几件事需要考虑。
您需要使用
filepath.Dir
而不是filepath.Base
. Base 给出路径的最后一个元素而不是基本目录。if info.IsDir(); len(params) > 2 {
只检查条件len(params) > 2
,info.IsDir()
已评估但未在任何地方使用。
引用:If with a short statement format in Go [1] [2]
应该是
if info.IsDir() {
if len(params) > 2 {
...
} else {
...
}
}
- 如果我对您的要求的理解是正确的。旧的基本路径需要从文件头和 替换为 param[2] 的值(如果可用)或假设我们维护一个相对文件结构(如果它是空的)。
变化:
var baseDir string
if info.IsDir(); len(params) > 2 {
baseDir = params[2]
} else {
baseDir = filepath.Base(params[0])
}
应该是
var baseDir, newBaseDir string
if info.IsDir() {
baseDir = filepath.Dir(params[0])
if len(params) > 2 {
newBaseDir = params[2]
}
}
和
header.Name = filepath.Join(strings.TrimPrefix(path, baseDir))
变成
header.Name = filepath.Join(newBaseDir, strings.TrimPrefix(path, baseDir))
关于unit-testing - 包含源和目标的 zip 文件夹,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50725437/