Go1.11标准库zip包及Demo

zip包提供了zip档案文件的读写服务。
参见http://www.pkware.com/documents/casestudies/APPNOTE.TXT
本包不支持跨硬盘的压缩。
关于ZIP64:
为了向下兼容,FileHeader同时拥有32位和64位的Size字段。64位字段总是包含正确的值,对普通格式的档案未见它们的值是相同的。对zip64格式的档案文件32位字段将是0xffffffff,必须使用64位字段。

Constants

const (
  Store   uint16 = 0
  Deflate uint16 = 8
)

Struct

Header

zip . File [struct]

type File struct {
  FileHeader
}

Function:

  • DataOffset
  • Open
func (f *File) DataOffset() (offset int64, err error)

DataOffset返回文件的可能存在的压缩数据相对于 zip 文件起始的偏移量。大多数调用者应使用 Open 代替,该方法会主动解压缩数据并验证校验和。

func (f *File) Open() (rc io.ReadCloser, err error)

Open方法返回一个 io.ReadCloser 接口,提供读取文件内容的方法。可以同时读取多个文件。

FileHeader

zip . FileHeader [struct]

FileHeader描述 zip 文件中的一个文件。参见 zip 的定义获取细节。

type FileHeader struct {
  Name string
  CreatorVersion     uint16
  ReaderVersion      uint16
  Flags              uint16
  Method             uint16
  ModifiedTime       uint16 // MS-DOS时间
  ModifiedDate       uint16 // MS-DOS日期
  CRC32              uint32
  CompressedSize     uint32 // 已弃用;请使用CompressedSize64
  UncompressedSize   uint32 // 已弃用;请使用UncompressedSize64
  CompressedSize64   uint64
  UncompressedSize64 uint64
  Extra              []byte
  ExternalAttrs      uint32 // 其含义依赖于CreatorVersion
  Comment            string
}

Function:

  • FileInfo
  • ModTime
  • Mode
  • SetModTime
  • SetMode
func (h *FileHeader) FileInfo() os.FileInfo

FileInfo返回一个根据h的信息生成的 os.FileInfo

func (h *FileHeader) ModTime() time.Time

返回最近一次修改的UTC时间。(精度2s)

func (h *FileHeader) Mode() (mode os.FileMode)

Mode返回h的权限和模式位

func (h *FileHeader) SetModTime(t time.Time)

将ModifiedTime和ModifiedDate字段设置为给定的UTC时间。(精度2s)

func (h *FileHeader) SetMode(mode os.FileMode)

SetMode修改h的权限和模式位。

ReadCloser

zip . ReadCloser [struct]

type ReadCloser struct {
  Reader
}

Function:

  • Close
func (rc *ReadCloser) Close() error

Close关闭 zip 文件,使它不能用于I/O。

Reader

zip . Reader [struct]

type Reader struct {
	r             io.ReaderAt
	File          []*File
	Comment       string
	decompressors map[uint16]Decompressor
}

Writer

zip . Writer [struct]

Writer类型实现了 zip 文件的写入器。

// Writer implements a zip file writer.
type Writer struct {
	cw          *countWriter
	dir         []*header
	last        *fileWriter
	closed      bool
	compressors map[uint16]Compressor
	comment     string

	// testHookCloseSizeOffset if non-nil is called with the size
	// of offset of the central directory at Close.
	testHookCloseSizeOffset func(size, offset uint64)
}

Function:

  • Close
  • Create
  • CreateHeader
func (w *Writer) Close() error

Close方法通过写入中央目录关闭该* Writer 。本方法不会也没办法关闭下层的 io.Writer 接口。

func (w *Writer) Create(name string) (io.Writer, error)

使用给出的文件名添加一个文件进 zip 文件。本方法返回一个 io.Writer 接口(用于写入新添加文件的内容)。文件名必须是相对路径,不能以设备或斜杠开始,只接受’/'作为路径分隔。新增文件的内容必须在下一次调用 CreateHeader 、Create或 Close 方法之前全部写入。

func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error)

使用给出的*FileHeader来作为文件的元数据添加一个文件进 zip 文件。本方法返回一个 io.Writer 接口(用于写入新添加文件的内容)。新增文件的内容必须在下一次调用CreateHeader、 Create 或 Close 方法之前全部写入。

Type

Compressor函数类型会返回一个 io.WriteCloser ,该接口会将数据压缩后写入提供的接口。关闭时,应将缓冲中的数据刷新到下层接口中。

type Compressor func(io.Writer) (io.WriteCloser, error)

Decompressor函数类型会返回一个 io.ReadCloser ,该接口的Read方法会将读取自提供的接口的数据提前解压缩。程序员有责任在读取结束时关闭该 io.ReadCloser 。

type Decompressor func(io.Reader) io.ReadCloser

Function

  • FileInfoHeader
func FileInfoHeader(fi os.FileInfo) (*FileHeader, error)

FileInfoHeader返回一个根据fi填写了部分字段的Header。因为 os.FileInfo 接口的Name方法只返回它描述的文件的无路径名,有可能需要将返回值的Name字段修改为文件的完整路径名。

  • NewReader
func NewReader(r io.ReaderAt, size int64) (*Reader, error)

NewReader返回一个从r读取数据的*Reader,r被假设其大小为size字节。

  • NewWriter
func NewWriter(w io.Writer) *Writer

NewWriter创建并返回一个将 zip 文件写入w的*Writer

  • OpenReader
func OpenReader(name string) (*ReadCloser, error)

OpenReader会打开name指定的 zip 文件并返回一个*ReadCloser

  • RegisterCompressor
func RegisterCompressor(method uint16, comp Compressor)

RegisterCompressor使用指定的方法ID注册一个Compressor类型函数。常用的方法Store和Deflate是内建的

  • RegisterDecompressor
func RegisterDecompressor(method uint16, d Decompressor)

RegisterDecompressor使用指定的方法ID注册一个Decompressor类型函数。

Demo代码

package main

import (
	"archive/zip"
	"fmt"
	"io"
	"os"
	"path"
	"path/filepath"
	"strings"
)

func main() {
	//zipFunc()
	uzipFunc()
}

压缩函数使用

//压缩Demo
func zipFunc() {
	zipTarget := "./zipFile.zip"
	fileFolder := "./fileFolder"
	zipfile, err := os.Create(zipTarget)
	if err != nil {
		// if file is exist then delete file
		if err == os.ErrExist {
			if err := os.Remove(zipTarget); err != nil {
				fmt.Println(err)
			}
		} else {
			fmt.Println(err)
		}
	}
	defer zipfile.Close()
	zipwriter := zip.NewWriter(zipfile)
	defer zipwriter.Close()
	sfileInfo, err := os.Stat(fileFolder)
	if err != nil {
		fmt.Println(err)
	}
	if !sfileInfo.IsDir() {
		zipFile(fileFolder, zipwriter)
	} else {
		zipFolder(fileFolder, zipwriter)
	}
}

解压缩函数使用

//解压缩Demo
func uzipFunc() {
	zipFile := "./zipFile.zip"
	unzipFolder := "./unzipFolder"
	unZipFile(zipFile, unzipFolder)
}

压缩函数使用

/**
功能:压缩文件
@directory:压缩目录
@zw:写入压缩文件的流
*/
func zipFolder(directory string, zw *zip.Writer) error {
	return filepath.Walk(directory, func(zipPath string, file os.FileInfo, err error) error {
		//read the file failure
		if file == nil {
			return err
		}
		if file.IsDir() {
			if directory == zipPath {
				return nil
			}
			fileFolder := filepath.Join(directory, strings.TrimPrefix(zipPath, directory))
			os.Mkdir(strings.TrimPrefix(directory, file.Name()), os.ModeDir)
			//如果是目录,递归目录
			return zipFolder(fileFolder, zw)
		}
		return zipFile(zipPath, zw)
	})
}

解压缩函数

func zipFile(sourceFile string, zw *zip.Writer) error {
	sfile, err := os.Open(sourceFile)
	if err != nil {
		fmt.Println(err)
		return err
	}
	defer sfile.Close()

	info, err := sfile.Stat()
	if err != nil {
		fmt.Println(err)
		return err
	}
	// 获取压缩头信息
	header, err := zip.FileInfoHeader(info)
	if err != nil {
		fmt.Println(err)
		return err
	}
	// 指定文件压缩方式 默认为 Store 方式 该方式不压缩文件 只是转换为zip保存
	header.Method = zip.Deflate
	header.Name = sourceFile
	fw, err := zw.CreateHeader(header)
	if err != nil {
		fmt.Println(err)
		return err
	}
	// 写入文件到压缩包中
	_, err = io.Copy(fw, sfile)
	if err != nil {
		fmt.Println(err)
		return err
	}
	return nil
}

解压缩函数

//untarFile 解压
func unZipFile(zipFile string, unzipPath string) error {
	//打开要解包的文件,tarFile是要解包的 .tar 文件的路径
	reader, err := zip.OpenReader(zipFile)
	if err != nil {
		fmt.Println(err)
	}
	//用 tr.Next() 来遍历包中的文件,然后将文件的数据保存到磁盘中
	for _, file := range reader.File {
		rc, err := file.Open()
		//先创建目录
		fileName := unzipPath + "/" + file.Name
		dir := path.Dir(fileName)
		_, err = os.Stat(dir)
		//如果err 为空说明文件夹已经存在,就不用创建
		if err != nil {
			err = os.MkdirAll(dir, os.ModePerm)
			if err != nil {
				fmt.Println(err)
				return err
			}
		}
		//创建空文件,准备写入解压后的数据
		fw, er := os.Create(fileName)
		if er != nil {
			fmt.Println(err)
			return er
		}
		defer fw.Close()
		// 写入解压后的数据
		_, er = io.CopyN(fw, rc, int64(file.UncompressedSize64))
		if er != nil {
			return er
		}
	}
	return nil
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值