tar
tar包实现了tar格式压缩文件的存取。本包覆盖大多数文件的变种,包括GUN和BSD生成的tar文件。
Constants
const (
// 类型
TypeReg = '0' // 普通文件
TypeRegA = '\x00' // 普通文件
TypeLink = '1' // 硬链接
TypeSymlink = '2' // 符号链接
TypeChar = '3' // 字符设备节点
TypeBlock = '4' // 块设备节点
TypeDir = '5' // 目录
TypeFifo = '6' // 先进先出队列节点
TypeCont = '7' // 保留位
TypeXHeader = 'x' // 扩展头
TypeXGlobalHeader = 'g' // 全局扩展头
TypeGNULongName = 'L' // 下一个文件记录有个长名字
TypeGNULongLink = 'K' // 下一个文件记录指向一个具有长名字的文件
TypeGNUSparse = 'S' // 稀疏文件
)
Variables
var (
ErrWriteTooLong = errors.New("archive/tar: write too long") //写入数据太长
ErrFieldTooLong = errors.New("archive/tar: header field too long") //头部太长
ErrWriteAfterClose = errors.New("archive/tar: write after close") //关闭后写入
)
var (
ErrHeader = errors.New("archive/tar: invalid tar header") //无效tar 头部
)
type Header
该结构体代表了一个tar归档的头部,一些字段可能不被填充,Header中主要包含文件相关信息。
type Header struct {
Name string // 文件名称
Mode int64 // 文件的权限和模式位
Uid int // 文件所有者的用户 ID
Gid int // 文件所有者的组 ID
Size int64 // 文件的字节长度
ModTime time.Time // 文件的修改时间
Typeflag byte // 文件的类型
Linkname string // 链接文件的目标名称
Uname string // 文件所有者的用户名
Gname string // 文件所有者的组名
Devmajor int64 // 字符设备或块设备的主设备号
Devminor int64 // 字符设备或块设备的次设备号
AccessTime time.Time // 文件的访问时间
ChangeTime time.Time // 文件的状态更改时间
}
FileInfoHeader方法
func FileInfoHeader(fi os.FileInfo, link string) (*Header, error)
FileInfoHeader返回一个根据fi填写了部分字段的Header。 如果fi描述一个符号链接,FileInfoHeader函数将link参数作为链接目标。如果fi描述一个目录,会在名字后面添加斜杠。因为os.FileInfo接口的Name方法只返回它描述的文件的无路径名,有可能需要将返回值的Name字段修改为文件的完整路径名。
FileInfo方法
func (h *Header) FileInfo() os.FileInfo
FileInfo返回该Header对应的文件信息。(os.FileInfo类型)
import (
"archive/tar"
"fmt"
"os"
)
func main() {
fileinfo, err := os.Stat("C:/Users/Administrator/Desktop/test.docx")
if err != nil {
fmt.Println(err)
}
h, err := tar.FileInfoHeader(fileinfo, "")
h.Linkname = "linkname"
h.Gname = "gname"
if err != nil {
fmt.Println(err)
}
fmt.Println(h.AccessTime, h.ChangeTime, h.Devmajor, h.Devminor, h.Gid, h.Gname, h.Linkname, h.ModTime, h.Mode, h.Name, h.Size, h.Typeflag, h.Uid, h.Uname, h.Xattrs)
// FileInfo
fileinfo2 := h.FileInfo()
fmt.Println(fileinfo2.Name())
}
type Reader
type Reader struct {
r io.Reader
err error
pad int64 //当前文件实体之后填充的
curr numBytesReader //当前文件实体的reader
hdrBuff [blockSize]byte // 读header中使用的buffer缓存
}
Reader提供了对一个tar档案文件的顺序读取。一个tar档案文件包含一系列文件。Next方法返回档案中的下一个文件(包括第一个),返回值可以被视为io.Reader来获取文件的数据。
NewReader方法
func NewReader(r io.Reader) *Reader
NewReader创建一个从r读取的Reader。
Next方法
func (tr *Reader) Next() (*Header, error)
转入tar档案文件下一记录,它会返回下一记录的头域。
Read方法
func (tr *Reader) Read(b []byte) (n int, err error)
从档案文件的当前记录读取数据,到达记录末端时返回(0, EOF),直到调用Next方法转入下一记录。
解压缩包的方法,从 .tar 文件中读出数据是通过 tar.Reader 完成的,所以首先要创建 tar.Reader,可以通过 tar.NewReader 方法来创建它,该方法要求提供一个 os.Reader 对象,以便从该对象中读出数据。可以先打开一个 .tar 文件,然后将该文件提供给 tar.NewReader 使用。这样就可以将 .tar 文件中的数据读出来了
func main() {
f, err := os.Open("C:/Users/Administrator/Downloads/test.tar")
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
// NewReader
r := tar.NewReader(f)
// Next
for hdr, err := r.Next(); err != io.EOF; hdr, err = r.Next() {
if err != nil {
fmt.Println(err)
return
}
fileinfo := hdr.FileInfo()
fmt.Println(fileinfo.Name())
f, err := os.Create("C:/Users/Administrator/Downloads/" + fileinfo.Name())
if err != nil {
fmt.Println(err)
}
defer f.Close()
_, err = io.Copy(f, r)
if err != nil {
fmt.Println(err)
}
}
}
type Writer
type Writer struct {
w io.Writer
pad int64 // 当前文件输入后要写入的填充量
curr fileWriter // 当前文件条目
hdr Header // Header浅拷贝
blk block // 用作临时本地存储的缓冲区
// err is a persistent error.
// It is only the responsibility of every exported method of Writer to
// ensure that this error is sticky.
err error
}
Writer类型提供了POSIX.1格式的tar档案文件的顺序写入。一个tar档案文件包含一系列文件。调用WriteHeader来写入一个新的文件,然后调用Write写入文件的数据,该记录写入的数据不能超过hdr.Size字节。
NewWriter方法
func NewWriter(w io.Writer) *Writer
NewWriter创建一个写入w的*Writer。
WriterHeader方法
func (tw *Writer) WriteHeader(hdr *Header) error
WriteHeader写入hdr并准备接受文件内容。如果不是第一次调用本方法,会调用Flush。在Close之后调用本方法会返回ErrWriteAfterClose。
Writer方法
func (tw *Writer) Write(b []byte) (n int, err error)
Write向tar档案文件的当前记录中写入数据。如果写入的数据总数超出上一次调用WriteHeader的参数hdr.Size字节,返回ErrWriteTooLong错误。
Flush方法
func (tw *Writer) Flush() error
Flush结束当前文件的写入。(可选的)
Close方法
func (tw *Writer) Close() error
Close关闭tar档案文件,会将缓冲中未写入下层的io.Writer接口的数据刷新到下层。
func main() {
f, err := os.Create("C:/Users/Administrator/Downloads/test10.tar") //创建一个tar文件
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
// NewWriter
tw := tar.NewWriter(f)
defer tw.Close()
fileinfo, err := os.Stat("C:/Users/Administrator/Downloads/test01.sh") //获取文件相关信息
if err != nil {
fmt.Println(err)
}
hdr, err := tar.FileInfoHeader(fileinfo, "")
if err != nil {
fmt.Println(err)
}
// WriterHeader
err = tw.WriteHeader(hdr) //写入头文件信息
if err != nil {
fmt.Println(err)
// return
}
f1, err := os.Open("C:/Users/Administrator/Downloads/test01.sh")
if err != nil {
fmt.Println(err)
return
}
m, err := io.Copy(tw, f1) //将文件test01.sh中信息写入压缩包中
if err != nil {
fmt.Println(err)
// return
}
fileinfo2, err := os.Stat("C:/Users/Administrator/Downloads/test02.sh") //获取文件相关信息
if err != nil {
fmt.Println(err)
}
hdr2, err := tar.FileInfoHeader(fileinfo2, "")
if err != nil {
fmt.Println(err)
}
// WriterHeader
err = tw.WriteHeader(hdr2) //写入头文件信息
if err != nil {
fmt.Println(err)
// return
}
f2, err := os.Open("C:/Users/Administrator/Downloads/test02.sh")
if err != nil {
fmt.Println(err)
return
}
m2, err := io.Copy(tw, f2) //将文件test02.sh中信息写入压缩包中
if err != nil {
fmt.Println(err)
// return
}
fmt.Println(m)
fmt.Println(m2)
}
有疑问加站长微信联系(非本文作者)