
tar.gz包压缩
type TarFileContent struct {
Name string
Content []byte
}
// 直接写到文件
func writeToFile(tarFileList []TarFileContent, file *os.File) error {
// 如果不是gzip格式, 可以直接用 tar.NewWriter(file)
gz := gzip.NewWriter(file)
tw := tar.NewWriter(gz)
defer func() {
tw.Close()
gz.Close()
}()
for _, f := range tarFileList {
hdr := &tar.Header{
Name: f.Name,
Mode: 0644,
Size: int64(len(f.Content)),
ModTime: time.Now(),
Typeflag: tar.TypeReg,
}
err := tw.WriteHeader(hdr)
if err != nil {
return err
}
_, err = tw.Write(f.Content)
if err != nil {
return err
}
}
return nil
}
// 写到内存
func writeToBuf(tarFileList []TarFileContent, buf *bytes.Buffer) error {
gz := gzip.NewWriter(buf)
tw := tar.NewWriter(gz)
defer func() {
tw.Close()
gz.Close()
}()
for _, f := range tarFileList {
hdr := &tar.Header{
Name: f.Name,
Mode: 0644,
Size: int64(len(f.Content)),
ModTime: time.Now(),
Typeflag: tar.TypeReg,
}
err := tw.WriteHeader(hdr)
if err != nil {
return err
}
_, err = tw.Write(f.Content)
if err != nil {
return err
}
}
return nil
}
// 测试写到内存
testContentList := []TarFileContent{
{
"meta.json",
`{"a":"aaa"}`,
},
{
"x1/x1.json",
`{"x1:"xxxx"}`,
},
{
"x2/x2.json",
`{"x2:"xxxx"}`,
},
}
buf := new(bytes.Buffer)
writeToBuf(testContentList, &buf)
tar.gz包解压
func parseTarData(tarData []byte) ([]TarFileContent, error) {
bf := bytes.NewBuffer(tarData)
// 如果不是gzip格式,可以直接用tar.NewReader(bf)
gr, err := gzip.NewReader(bf)
if err != nil {
return nil, err
}
defer gr.Close()
tr := tar.NewReader(gr)
tarContentList := make([]TarFileContent, 0)
for {
hdr, err := tr.Next()
if err == io.EOF {
break // End of archive
}
if err != nil {
return nil, err
}
if hdr.Typeflag == tar.TypeDir {
continue
}
fileData, err := ioutil.ReadAll(tr)
if err != nil {
return nil, err
}
tarContentList = append(tarContentList, TarFileContent{Name: hdr.Name, **Content:** fileData})
}
}
return tarContentList, nil
}
坑
在压缩tar包时,写完所有二进制之后,需要先把 tw.Close() , 再把 gw.Close() , 这两个顺序一定不能颠倒,不然格式会出错,少写入512个byte。
