前言
在实际业务中,我们可以使用zip文件的形式来实现文件归档,压缩体积等操作。Go的标准库中的archive包也提供了对tar和zip格式文件的归档和解压操作。本篇先就zip格式的文件进行讲解。
定义
常量
const (
Store uint16 = 0 // no compression
Deflate uint16 = 8 // DEFLATE compressed
)
zip包提供了两种压缩算法支持
store
: 不压缩
Deflate
:使用Deflate算法的压缩方式,其中DEFLATE是同时使用了LZ77算法与哈夫曼编码(Huffman Coding)的一个无损数据压缩算法。
FileHeader
type FileHeader struct {
// Name是文件名,它必须是相对路径,不能以设备或斜杠开始,只接受'/'作为路径分隔符
Name string
CreatorVersion uint16
ReaderVersion uint16
Flags uint16
Method uint16
ModifiedTime uint16 // MS-DOS时间
ModifiedDate uint16 // MS-DOS日期
CRC32 uint32
CompressedSize64 uint64
UncompressedSize64 uint64
Extra []byte
ExternalAttrs uint32 // 其含义依赖于CreatorVersion
Comment string
}
-
func FileInfoHeader(fi os.FileInfo) (*FileHeader, error) 根据os.FileInfo类型的参数,创建并返回包含部分信息的FileHeader
-
func (h *FileHeader) FileInfo() os.FileInfo 返回一个根据FileHeader的信息生成的os.FileInfo。
-
func (h *FileHeader) ModTime() time.Time
获取最后一次修改时间 -
func (h *FileHeader) SetModTime(t time.Time)
设置更改时间 -
func (h *FileHeader) Mode() (mode os.FileMode)
返回FileHeader对应文件的文件类型和权限信息 -
func (h *FileHeader) SetMode(mode os.FileMode) 设置FileHeader对应文件的文件类型和权限信息
File
type File struct {
FileHeader
// contains filtered or unexported fields
}
- func (f *File) Open() (rc io.ReadCloser, err error) Open方法返回一个io.ReadCloser接口,提供读取文件内容的方法。可以同时读取多个文件。
压缩
Writer
func NewWriter(w io.Writer) *Writer
func (w *Writer) Close() error
func (w *Writer) Create(name string) (io.Writer, error)
func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error)
- NewWriter创建并返回一个将zip文件写入w的*Writer
- Create方法传入添加到zip文件中的文件名,返回一个io.Writer,用于将内容写入该文件。参数name只接受相对路径。
- CreateHeader使用FileHeader类型创建添加zip文件中的文件,同样返回一个io.Writer,用于将内容写入该文件。
Example
func Zip(filePath string, w io.ReadWriter) error {
f, err := ioutil.ReadDir(filePath)
if err != nil {
fmt.Println(err)
}
zipFile, _ := os.Create("test.zip")
w := zip.NewWriter(zipFile)
defer w.Close()
for _, file := range f {
fw, _ := w.Create(file.Name())
filecontent, err := ioutil.ReadFile(filePath + file.Name())
if err != nil {
fmt.Println(err)
}
n, err := fw.Write(filecontent)
if err != nil {
fmt.Println(err)
}
}
}
解压
Reader
type Reader struct {
r io.ReaderAt
File []*File
Comment string
decompressors map[uint16]Decompressor
}
type ReadCloser struct {
Reader
f *os.File
}
func OpenReader(name string) (*ReadCloser, error)
func NewReader(r io.ReaderAt, size int64) (*Reader, error)
func (rc *ReadCloser) Close() error //关闭ReadCloser
- 通过OpenReader,传入文件名,返回一个该文件的ReadCloser类型的对象
- NewReader返回一个从r读取数据的*Reader,r被假设其大小为size字节。
Example
func UnZip(fileName, filePath string, w io.ReadWriter) error {
f, err := zip.OpenReader(filePath + "/" + fileName) //读取zip文件
if err != nil {
fmt.Println(err)
}
defer f.Close()
for _, file := range f.File {
rc, err := file.Open()
if err != nil {
fmt.Println(err)
}
f, err := os.Create(filePath + file.Name)
if err != nil {
fmt.Println(err)
}
defer f.Close()
n, err := io.Copy(f, rc)
if err != nil {
fmt.Println(err)
}
}
}