<!-- lang: cpp -->
package main
import (
"archive/tar"
"io"
"io/ioutil"
"log"
"os"
"path"
)
func main() {
//TarDynamicContent()
//UnTar("D:/home/mytar.tar", "D:/home/mytar/")
TarExistFile("D:/home/gif/111.gif")
}
func UnTar(srcTar string, dstDir string) {
// 清理路径字符串
dstDir = path.Clean(dstDir) + "/"
// 打开要解包的文件
fr, er := os.Open(srcTar)
if er != nil {
log.Fatalln(er)
}
defer fr.Close()
// 创建 tar.Reader,准备执行解包操作
tr := tar.NewReader(fr)
// 遍历包中的文件
for hdr, er := tr.Next(); er != io.EOF; hdr, er = tr.Next() {
if er != nil {
log.Fatalln(er)
continue
}
// 获取文件信息
fi := hdr.FileInfo()
// 获取绝对路径
dstFullPath := dstDir + hdr.Name
if hdr.Typeflag == tar.TypeDir {
// 创建目录
os.MkdirAll(dstFullPath, fi.Mode().Perm())
// 设置目录权限
os.Chmod(dstFullPath, fi.Mode().Perm())
} else {
// 创建文件所在的目录
os.MkdirAll(path.Dir(dstFullPath), os.ModePerm)
// 将 tr 中的数据写入文件中
if er := unTarFile(dstFullPath, tr); er != nil {
log.Fatalln(er)
}
// 设置文件权限
os.Chmod(dstFullPath, fi.Mode().Perm())
}
}
}
// 因为要在 defer 中关闭文件,所以要单独创建一个函数
func unTarFile(dstFile string, tr *tar.Reader) error {
// 创建空文件,准备写入解包后的数据
fw, er := os.Create(dstFile)
if er != nil {
return er
}
defer fw.Close()
// 写入解包后的数
_, er = io.Copy(fw, tr)
if er != nil {
return er
}
return nil
}
func TarExistFile(srcPath string) {
// 创建空的目标文件
fw, _ := os.Create("D:/home/mytar-file.tar")
defer fw.Close()
// 创建 tar.Writer,执行打包操作
tw := tar.NewWriter(fw)
defer func() {
tw.Flush()
tw.Close()
}()
// 获取文件或目录信息
fi, _ := os.Stat(srcPath)
// 获取要打包的文件或目录的所在位置(parent dir) 和 名称
parentDir, dirOrFileName := path.Split(path.Clean(srcPath))
// 开始打包
if fi.IsDir() {
tarDir(parentDir, dirOrFileName, tw, fi)
} else {
tarFile(parentDir, dirOrFileName, tw, fi)
}
}
// 因为要执行遍历操作,所以要单独创建一个函数
func tarDir(parentDir, dirName string, tw *tar.Writer, fi os.FileInfo) {
// 写入目录信息
if len(dirName) > 0 {
hdr, _ := tar.FileInfoHeader(fi, "")
hdr.Name = dirName
tw.WriteHeader(hdr)
}
dirFull := parentDir + dirName + "/"
// 获取 srcFull 下的文件或子目录列表
fis, _ := ioutil.ReadDir(dirFull)
// 开始遍历
for _, nfi := range fis {
if nfi.IsDir() {
tarDir(parentDir, dirName+"/"+nfi.Name(), tw, nfi)
} else {
tarFile(parentDir, dirName+"/"+nfi.Name(), tw, nfi)
}
}
}
// 因为要在 defer 中关闭文件,所以要单独创建一个函数
func tarFile(fileDir, filename string, tw *tar.Writer, fi os.FileInfo) {
// 获取完整路径
filepath := fileDir + filename
log.Println("file: ", filepath)
// 写入文件信息
hdr, _ := tar.FileInfoHeader(fi, "")
hdr.Name = filename
tw.WriteHeader(hdr)
fb, _ := ioutil.ReadFile(filepath)
tw.Write(fb)
}
func TarDynamicContent() {
// 创建空的目标文件
fw, er := os.Create("D:/home/mytar.tar")
if er != nil {
log.Fatalln(er)
}
defer fw.Close()
// 创建 tar.Writer,执行打包操作
tw := tar.NewWriter(fw)
defer func() {
tw.Flush()
// 这里要判断 tw 是否关闭成功,如果关闭失败,则 .tar 文件可能不完整
if er := tw.Close(); er != nil {
log.Fatalln(er)
}
}()
//要打包的内容
var files = []struct {
Name, Body string
}{
{"readme.txt", "thie archive contains some text files"},
{"gopher.txt", "Gopher names:\nGeorge \nGeoffrey\nGonzo"},
{"todo.txt", "Get animal handling licence"},
}
//写入tar
for _, file := range files {
hdr := &tar.Header{
Name: file.Name,
Size: int64(len(file.Body)),
}
if err := tw.WriteHeader(hdr); err != nil {
log.Fatalln(err)
}
if _, err := tw.Write([]byte(file.Body)); err != nil {
log.Fatalln(err)
}
}
}