此代码尝试将某些文本转换为tar
文件并解压缩。
tar
的代码有效但看起来我做错了
因为untar
同一个文件不起作用。
当我解压缩手动tar.gz与OS GUI的文件时,它可以正常工作 不在此代码中。
http://play.golang.org/p/diTOojUuBX
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)
}
}
}
答案 0 :(得分:2)
在我看来,有两个问题。
您正在使用defer关闭tar writer和gzip writer,但是只在当前作用域结束时才执行。由于您在一个函数中运行此函数,因此当您尝试读取untar并且可能导致问题(例如文件未完全刷新)时,文件句柄仍将打开。
创建tarball时,您没有在标题中设置Typeflag
。虽然GNU tar可能会处理这个问题,但假设Typeflag为'0',Go可能不会。根据文档http://www.gnu.org/software/tar/manual/html_node/Standard.html,常规文件的Typeflag是字节'0'。这可能意味着您需要在代码中的每个资源(目录,文件,链接等)上设置Typeflag。
我重写了以下代码,现在它正在为我工作。 (注意:将所有内容存储为REGTYPE)
http://play.golang.org/p/3B7F_axr-i
修改强>
啊哈,我现在知道#2的问题了。 tar的Go库使用FileInfoHeader来确定标题的部分,如Typeflag。由于您的文件不是系统上的真正文件,因此无法填写相应的Typeflag。
GNU tar显然知道如何处理这个问题,或者也许会尽力解决这个问题并在这种情况下取得成功。