golang访问tar文件
下面例子提取一个tar文件的内容:
package main
import (
"io"
"os"
"fmt"
"path"
"encoding/json"
"archive/tar"
)
func extract(tarfile string) {
reader, err := os.Open(tarfile)
if err != nil {
fmt.Printf("ERROR: cannot read tar file, error=[%v]\n", err)
return
}
defer reader.Close()
tarReader := tar.NewReader(reader)
for {
header, err := tarReader.Next()
if err == io.EOF {
break
} else if err != nil {
fmt.Printf("ERROR: cannot read tar file, error=[%v]\n", err)
return
}
j, err := json.Marshal(header)
if err != nil {
fmt.Printf("ERROR: cannot parse header, error=[%v]\n", err)
return
}
fmt.Printf("header=%s\n", string(j))
info := header.FileInfo()
if info.IsDir() {
if err = os.MkdirAll(header.Name, 0755); err != nil {
fmt.Printf("ERROR: cannot mkdir file, error=[%v]\n", err)
return
}
} else {
if err = os.MkdirAll(path.Dir(header.Name), 0755); err != nil {
fmt.Printf("ERROR: cannot file mkdir file, error=[%v]\n", err)
return
}
file, err:= os.OpenFile(header.Name, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, info.Mode())
if err != nil {
fmt.Printf("ERROR: cannot open file, error=[%v]\n", err)
return
}
defer file.Close()
_, err =io.Copy(file, tarReader)
if err != nil {
fmt.Printf("ERROR: cannot write file, error=[%v]\n", err)
return
}
}
}
}
tar文件的格式定义:
https://www.gnu.org/software/tar/manual/html_node/Standard.html
每一个文件包含一个512字节的头部信息,然后是文件内容;所以对于小文件生成的tar文件反而比原文件大很多。每一个原文件打到tar里面至少包含1024字节(512的头信息,然后是文件内容,不足512字节的后面补零);所以如果原文件大小为一个字节大小,生成的tar文件就会有1024字节大小,结论就是小文件不宜使用tar.gz压缩存储。
使用tar很自然的就会想到gz,因为tar.gz。
下面的模板例子用来处理tar.gz的读写:
读取tar.gz文件内容:
body := bytes.NewReader([]byte{...})
gr, err := gzip.NewReader(body)
tr := tar.NewReader(gr)
for {
header, err := tr.Next()
if err != nil {
// We only get here if there are no more entries to scan
break
}
HANLD_AN_ENTRY
}
生成tar.gz文件:
payload := bytes.NewBuffer(nil)
gw := gzip.NewWriter(payload)
tw := tar.NewWriter(gw)
for _, file := range files {
info, err := os.Stat(file)
header, err := tar.FileInfoHeader(info, file)
err = tw.WriteHeader(header);
fd, err := os.Open(file)
_, err := io.Copy(tw, bufio.NewReader(fd));
}
tw.Close()
gw.Close()
write payload.Bytes() into file.
网友评论