代码之家  ›  专栏  ›  技术社区  ›  07_05_GuyT

包含源和目标的zip文件夹

  •  1
  • 07_05_GuyT  · 技术社区  · 7 年前

    我使用以下代码将某个文件夹压缩到给定的路径,im当前面临的问题是,我需要将某个包含内容的文件夹压缩到特定的目标中,而不是在同一个目录中

    例如

    路径中的文件夹 来源

    "/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
    }
    

    1 回复  |  直到 7 年前
        1
  •  2
  •   John S Perayil    7 年前

    用于测试:

    可以传递模拟变量 zipFile 这就意味着 io.Writer 接口,作为函数的参数 zipit 并与测试中的预期数据进行比较。
    此外,您还需要目标中的一组已知文件,以便将其与mock中的值进行比较。

    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() 已评估但未在任何地方使用。

    参考:如果在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))