golang中archive/tar包用法

tar包实现对tar归档文件的访问,旨在覆盖大部分的类型,包括GNU和BSD产生的tars。

常量

const (

    // Types
    TypeReg           = '0'    // 普通文件
    TypeRegA          = '\x00' // 普通文件
    TypeLink          = '1'    // 硬连接
    TypeSymlink       = '2'    // 符号连接,软连接
    TypeChar          = '3'    // 字符设备节点
    TypeBlock         = '4'    // 块设备节点
    TypeDir           = '5'    // 目录
    TypeFifo          = '6'    // fifo node
    TypeCont          = '7'    // 保留项
    TypeXHeader       = 'x'    // 可扩展头部
    TypeXGlobalHeader = 'g'    // 全局扩展头
    TypeGNULongName   = 'L'    // Next file has a long name
    TypeGNULongLink   = 'K'    // Next file symlinks to a file w/ a long name
    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")  //无效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 // 文件的状态更改时间
}

func FileInfoHeader(fi os.FileInfo, link string) (*Header, error)//该函数通过os.fileInfo便可创建一个Header,Header中大部分内容自动填充,一些内容需要自己设定。

func (h *Header) FileInfo() os.FileInfo  //该函数获取该Header的os.FileInfo信息

举例说明Header用法:

package main

import (
	"archive/tar"
	"fmt"
	"os"
)

func main() {
	fileinfo, err := os.Stat("/home/chenbaoke/test.go")
	if err != nil {
		fmt.Println(err)
	}
	h, err := tar.FileInfoHeader(fileinfo, "")
	h.Linkname = "haha"
	h.Gname = "test"
	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)

}
输出结果如下:
2015-08-28 21:26:03.636592126 +0800 CST 2015-08-28 21:26:03.092592112 +0800 CST 0 0 1000 test haha 2015-08-28 21:26:03.092592112 +0800 CST 33206 test.go 581
 48 1000  map[]

由此可见,通过fileinfoheader可以创建tar.header,并自动填写了tar.Header 中的大部分信息,当然,还有一些信息无法从 os.FileInfo 中获取,所以需要你自己去补充,
如Linkname,Gname等。

type Reader

type Reader struct {
    r       io.Reader
    err     error
    pad     int64           //当前文件实体之后填充的
    curr    numBytesReader  //当前文件实体的reader
    hdrBuff [blockSize]byte // 读header中使用的buffer缓存
}<span style="font-size:12px;">
</span>

func NewReader(r io.Reader) *Reader// 从r中创建一个新的reader

func (tr *Reader) Next() (*Header, error)//该函数指向tar文件的下一个实体,在输入的最后返回io.EOF

func (tr *Reader) Read(b []byte) (n int, err error)//该函数读取在tar中当前实体,当读取到实体的结束位置时,返回io.EOF,当调用Next时,读取下一个实体。

解压缩包的方法,从 .tar 文件中读出数据是通过 tar.Reader 完成的,所以首先要创建 tar.Reader,可以通过 tar.NewReader 方法来创建它,该方法要求提供一个 os.Reader 对象,以便从该对象中读出数据。可以先打开一个 .tar 文件,然后将该文件提供给 tar.NewReader 使用。这样就可以将 .tar 文件中的数据读出来了:

举例说明其用法:

package main

import (
	"archive/tar"
	"fmt"
	"io"
	"os"
)

func main() {
	f, err := os.Open("/home/chenbaoke/10.tar")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()
	r := tar.NewReader(f)
	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("/home/chenbaoke/develop/" + 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
    		err        error
    		nb         int64 // 未写入的字节数
    		pad        int64 // 该实体之后需要写入的数量
    		closed     bool
    		usedBinary bool            // whether the binary numeric field extension was used
    		preferPax  bool            // use pax header instead of binary numeric header
    		hdrBuff    [blockSize]byte // buffer to use in writeHeader when writing a regular header
    		paxHdrBuff [blockSize]byte // buffer to use in writeHeader when writing a pax header
    	}

func NewWriter(w io.Writer) *Writer  //创建一个新的writer,向w中写入。

func (tw *Writer) Close() error //关闭tar归档文件,并将未写入的数据写入底层writer。

func (tw *Writer) Flush() error //完成写当前文件

func (tw *Writer) Write(b []byte) (n int, err error)

func (tw *Writer) WriteHeader(hdr *Header) error//该函数将hdr写入tar文件中,如果hdr不是第一个header,该函数调用flush。在调用close之后在调用该函数就会报错ErrWriteAfterClose。

举例说明如何写入一个tar文件。

package main

import (
	"archive/tar"
	"fmt"
	"io"
	"os"
)

func main() {
	f, err := os.Create("/home/chenbaoke/10.tar")  //创建一个tar文件
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()

	tw := tar.NewWriter(f)
	defer tw.Close()

	fileinfo, err := os.Stat("/home/chenbaoke/1.go")  //获取文件相关信息
	if err != nil {
		fmt.Println(err)
	}
	hdr, err := tar.FileInfoHeader(fileinfo, "")
	if err != nil {
		fmt.Println(err)
	}

	err = tw.WriteHeader(hdr)    //写入头文件信息
	if err != nil {
		fmt.Println(err)
		// return
	}

	f1, err := os.Open("/home/chenbaoke/1.go")
	if err != nil {
		fmt.Println(err)
		return
	}
	m, err := io.Copy(tw, f1)   //将文件1.go中信息写入压缩包中
	if err != nil {
		fmt.Println(err)
		// return
	}
	fmt.Println(m)
}

参考:https://golang.org/pkg/archive/tar/

GoLove博客:   http://www.cnblogs.com/golove/p/3454630.html

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-12 16:13:30

golang中archive/tar包用法的相关文章

golang中的rpc包用法

RPC,即 Remote Procedure Call(远程过程调用),说得通俗一点就是:调用远程计算机上的服务,就像调用本地服务一样. 我所在公司的项目是采用基于Restful的微服务架构,随着微服务之间的沟通越来越频繁,就希望可以做成用rpc来做内部的通讯,对外依然用Restful.于是就想到了golang标准库的rpc包和google的grpc. 这篇文章重点了解一下golang的rpc包. 介绍 golang的rpc支持三个级别的RPC:TCP.HTTP.JSONRPC.但Go的RPC包

golang中container/heap包源码分析

学习golang难免需要分析源码包中一些实现,下面就来说说container/heap包的源码 heap的实现使用到了小根堆,下面先对堆做个简单说明 1. 堆概念 堆是一种经过排序的完全二叉树,其中任一非终端节点的数据值均不大于(或不小于)其左孩子和右孩子节点的值. 最大堆和最小堆是二叉堆的两种形式. 最大堆:根结点的键值是所有堆结点键值中最大者. 最小堆:根结点的键值是所有堆结点键值中最小者. 2. heap 树的最小元素在根部,为index 0. heap包对任意实现了heap接口的类型提供

golang中container/list包源码分析

golang源码包中container/list实际上是一个双向链表 提供链表的一些基本操作,下面就结合定义和接口进行下说明 1. 定义 // Element is an element of a linked list. type Element struct { // Next and previous pointers in the doubly-linked list of elements. // To simplify the implementation, internally a

golang格式化输出-fmt包用法详解

注意:我在这里给出golang查询关于包的使用的地址:https://godoc.org    声明: 此片文章并非原创,大多数内容都是来自:https://godoc.org/fmt,通过谷歌翻译进行翻译而来.   import "fmt" fmt包实现了类似C语言printf和scanf的格式化I/O.格式化verb('verb')源自C语言但更简单. Printing verb: 通用: 1 %v 值的默认格式表示.当输出结构体时,扩展标志(%+v)会添加字段名 2 %#v 值的

关于Golang中database/sql包的学习

go-sql-driver 请求一个连接的函数有好几种,执行完毕处理连接的方式稍有差别,大致如下: db.Ping() 调用完毕后会马上把连接返回给连接池. db.Exec() 调用完毕后会马上把连接返回给连接池,但是它返回的Result对象还保留这连接的引用,当后面的代码需要处理结果集的时候连接将会被重用. db.Query() 调用完毕后会将连接传递给sql.Rows类型,当然后者迭代完毕或者显示的调用.Clonse()方法后,连接将会被释放回到连接池. db.QueryRow()调用完毕后

golang 中 sync.Mutex 和 sync.RWMutex

介绍 golang 中的 sync 包实现了两种锁: Mutex:互斥锁 RWMutex:读写锁,RWMutex 基于 Mutex 实现 Mutex(互斥锁) Mutex 为互斥锁,Lock() 加锁,Unlock() 解锁 在一个 goroutine 获得 Mutex 后,其他 goroutine 只能等到这个 goroutine 释放该 Mutex 使用 Lock() 加锁后,不能再继续对其加锁,直到利用 Unlock() 解锁后才能再加锁 在 Lock() 之前使用 Unlock() 会导

golang中解决tcp传输中的粘包问题

"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> golang中解决tcp传输中的粘包问题 - Programmer小卫 - 博客频道 - CSDN.NET Programmer小卫 故不积跬步,无以至千里.不积小流,无以成江海. 目录视图 摘要视图 订阅 [活动]2017 CSDN博客专栏评选 &nbsp [5月书

tar只解压tar包中某个文件

如果tar包很大,而只想解压出其中某个文件.方法如下: 只想解压出Redis-1.972.tar 中的Changes文件,来查看有哪些更改. [[email protected] ~]# tar -tf Redis-1.972.tar Redis-1.972 Redis-1.972/README Redis-1.972/Changes Redis-1.972/LICENSE Redis-1.972/dist.ini Redis-1.972/META.yml Redis-1.972/MANIFES

Ubuntu 16.04 LTS软件包管理基本操作使用APT简化命令行下面我们列出 Ubuntu 16.04 LTS 中使用 ATP 命令与老版本 Ubuntu 中软件包管理的用法对比: Ubuntu 16.04 LTS 老版本Ubuntu apt install 包名 替代 apt-get install 包名 apt remove 包名 替代 apt-get remove 包名 apt se

前文 Ubuntu 16.04 新特性中我们已经介绍过,随着 Ubuntu 16.04 LTS 的发布,Ubuntu 的软件包管理命令也发生了变化,新系统采用了 Debian 项目中所使用的 APT(Advanced Package Tool)来完成各种的不同的任务,ATP 命令全面取代了我们之前在 Linux 软件包管理基本操作入门中所介绍的 apt-get.apt-cache 等功能. ATP 在创建之初便是为了解决大量软件包管理所遇到的问题,希望结束类似 Linux 早期系统依赖的一大弊病