import "archive/tar"
tar包实现了tar格式压缩文件的存取。本包目标是覆盖大多数tar的变种,包括GNU和BSD生成的tar文件。
参见:
http://www.freebsd.org/cgi/man.cgi?query=tar&sektion=5 http://www.gnu.org/software/tar/manual/html_node/Standard.html http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html
// Create a buffer to write our archive to. buf := new(bytes.Buffer) // Create a new tar archive. tw := tar.NewWriter(buf) // Add some files to the archive. var files = []struct { Name, Body string }{ {"readme.txt", "This archive contains some text files."}, {"gopher.txt", "Gopher names:\nGeorge\nGeoffrey\nGonzo"}, {"todo.txt", "Get animal handling licence."}, } 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) } } // Make sure to check the error on Close. if err := tw.Close(); err != nil { log.Fatalln(err) } // Open the tar archive for reading. r := bytes.NewReader(buf.Bytes()) tr := tar.NewReader(r) // Iterate through the files in the archive. for { hdr, err := tr.Next() if err == io.EOF { // end of tar archive break } if err != nil { log.Fatalln(err) } fmt.Printf("Contents of %s:\n", hdr.Name) if _, err := io.Copy(os.Stdout, tr); err != nil { log.Fatalln(err) } fmt.Println() }
Output:
Contents of readme.txt: This archive contains some text files. Contents of gopher.txt: Gopher names: George Geoffrey Gonzo Contents of todo.txt: Get animal handling licence.
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' // 稀疏文件 )
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") )
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 // 字符设备或块设备的major number Devminor int64 // 字符设备或块设备的minor number AccessTime time.Time // 访问时间 ChangeTime time.Time // 状态改变时间 Xattrs map[string]string }
Header代表tar档案文件里的单个头。Header类型的某些字段可能未使用。
func FileInfoHeader(fi os.FileInfo, link string) (*Header, error)
FileInfoHeader返回一个根据fi填写了部分字段的Header。 如果fi描述一个符号链接,FileInfoHeader函数将link参数作为链接目标。如果fi描述一个目录,会在名字后面添加斜杠。因为os.FileInfo接口的Name方法只返回它描述的文件的无路径名,有可能需要将返回值的Name字段修改为文件的完整路径名。
func (h *Header) FileInfo() os.FileInfo
FileInfo返回该Header对应的文件信息。(os.FileInfo类型)
type Reader struct {
// 内含隐藏或非导出字段
}
Reader提供了对一个tar档案文件的顺序读取。一个tar档案文件包含一系列文件。Next方法返回档案中的下一个文件(包括第一个),返回值可以被视为io.Reader来获取文件的数据。
func NewReader(r io.Reader) *Reader
NewReader创建一个从r读取的Reader。
func (tr *Reader) Next() (*Header, error)
转入tar档案文件下一记录,它会返回下一记录的头域。
func (tr *Reader) Read(b []byte) (n int, err error)
从档案文件的当前记录读取数据,到达记录末端时返回(0, EOF),直到调用Next方法转入下一记录。
type Writer struct {
// 内含隐藏或非导出字段
}
Writer类型提供了POSIX.1格式的tar档案文件的顺序写入。一个tar档案文件包含一系列文件。调用WriteHeader来写入一个新的文件,然后调用Write写入文件的数据,该记录写入的数据不能超过hdr.Size字节。
func NewWriter(w io.Writer) *Writer
NewWriter创建一个写入w的*Writer。
func (tw *Writer) WriteHeader(hdr *Header) error
WriteHeader写入hdr并准备接受文件内容。如果不是第一次调用本方法,会调用Flush。在Close之后调用本方法会返回ErrWriteAfterClose。
func (tw *Writer) Write(b []byte) (n int, err error)
Write向tar档案文件的当前记录中写入数据。如果写入的数据总数超出上一次调用WriteHeader的参数hdr.Size字节,返回ErrWriteTooLong错误。
func (tw *Writer) Flush() error
Flush结束当前文件的写入。(可选的)
func (tw *Writer) Close() error
Close关闭tar档案文件,会将缓冲中未写入下层的io.Writer接口的数据刷新到下层。