Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从Go中的tar文件中提取_Go_Gzip_Tar - Fatal编程技术网

从Go中的tar文件中提取

从Go中的tar文件中提取,go,gzip,tar,Go,Gzip,Tar,此代码尝试将一些文本放入tar文件中,并将其解压缩。 tar的代码工作正常,但似乎我做错了什么 因为untar同一个文件不起作用 当我用OSGUI解压我手动tar.gz的文件时,它可以工作,但是 不在这个代码中 在我看来,有两个问题 您正在使用defer关闭tar writer和gzip writer,但是只有在当前作用域结束时才延迟执行。由于您正在运行这个多功能一体的函数,所以当您尝试读取到untar时,您的文件句柄仍将打开,这可能会导致问题(例如,文件可能尚未完全刷新) 创建tarball

此代码尝试将一些文本放入
tar
文件中,并将其解压缩。
tar
的代码工作正常,但似乎我做错了什么 因为
untar
同一个文件不起作用

当我用OSGUI解压我手动tar.gz的文件时,它可以工作,但是 不在这个代码中


在我看来,有两个问题

  • 您正在使用defer关闭tar writer和gzip writer,但是只有在当前作用域结束时才延迟执行。由于您正在运行这个多功能一体的函数,所以当您尝试读取到untar时,您的文件句柄仍将打开,这可能会导致问题(例如,文件可能尚未完全刷新)

  • 创建tarball时,您没有在标题中设置
    Typeflag
    。虽然GNU tar可以处理这个问题,但假设Typeflag为“0”,Go可能不会。根据文档,常规文件的Typeflag是字节“0”。这可能意味着您需要在代码中的每个资源(目录、文件、链接等)上设置Typeflag

  • 我像下面这样重写了你的代码,现在它对我起作用了。(注意:将所有内容存储为REGTYPE)

    编辑
    啊哈,我现在知道2的问题了。tar的Go库用于确定标题的某些部分,如Typeflag。由于您的文件不是系统上的真正文件,因此无法填写相应的Typeflag

    GNUTAR显然知道如何处理这个问题,或者可能会尽最大努力解决这个问题,并且在这种情况下取得了成功

    func main() {
            mpath := "a.tar.gz"
            // defer os.Remove(mpath)
            f, err := overwrite(mpath)
            defer f.Close()
            if err != nil {
                    panic(err)
            }
            gw := gzip.NewWriter(f)
            defer gw.Close()
            if err != nil {
                    panic(err)
            }
            tw := tar.NewWriter(gw)
            for _, file := range files {
                    hdr := &tar.Header{
                            Name: file.Name,
                            Mode: 0600,
                            Size: int64(len(file.Body)),
                    }
                    if err := tw.WriteHeader(hdr); err != nil {
                            panic(err)
                    }
                    if _, err := tw.Write([]byte(file.Body)); err != nil {
                            panic(err)
                    }
            }
            // Make sure to check the error on Close.
            if err := tw.Close(); err != nil {
                    panic(err)
            }
    
            fr, err := read(mpath)
            defer fr.Close()
            if err != nil {
                    panic(err)
            }
            gr, err := gzip.NewReader(fr)
            defer gr.Close()
            if err != nil {
                    panic(err)
            }
            tr := tar.NewReader(gr)
            for {
                    hdr, err := tr.Next()
                    if err == io.EOF {
                            // end of tar archive
                            break
                    }
                    if err != nil {
                            panic(err)
                    }
                    path := hdr.Name
                    switch hdr.Typeflag {
                    case tar.TypeDir:
                            if err := os.MkdirAll(path, os.FileMode(hdr.Mode)); err != nil {
                                    panic(err)
                            }
                    case tar.TypeReg:
                            ow, err := overwrite(path)
                            defer ow.Close()
                            if err != nil {
                                    panic(err)
                            }
                            if _, err := io.Copy(ow, tr); err != nil {
                                    panic(err)
                            }
                    default:
                            fmt.Printf("Can't: %c, %s\n", hdr.Typeflag, path)
                    }
            }
    }