首页 > 代码库 > archive/tar

archive/tar

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)
    }
}

}

archive/tar