前言
在之前的文章中提到在Go中可以使用zip和tar类型进行文件归档,那么当我们的业务中如果涉及到文件的压缩和解压,Go的标准库中的comporess包也提供了一系列的算法实现,本篇主要聊聊常见的gzip类型的压缩和解压。
Header
type Header struct {
Comment string // 注释
Extra []byte // 额外数据
ModTime time.Time // 修改时间
Name string // 文件名
OS byte // 操作系统类型
}
每一个gzip文件都有一个Header类型的结构体来保存关于该文件相关的信息。其中Reader和Writer都包含了Header类型的字段,可以直接通过点语法供调用者使用。
解压/Reader
type Reader struct {
Header // valid after NewReader or Reader.Reset
r flate.Reader
decompressor io.ReadCloser
digest uint32 // CRC-32, IEEE polynomial (section 8)
size uint32 // Uncompressed size (section 2.3.1)
buf [512]byte
err error
multistream bool
}
func NewReader(r io.Reader) (*Reader, error)
func (z *Reader) Reset(r io.Reader) error
func (z *Reader) Read(p []byte) (n int, err error)
func (z *Reader) Close() error
- 使用
NewReader()来创建并返回一个从io.Reader类型的参数读取的带解压输入流的Reader类型的对象的指针。 - 使用
Reset方法可以重置已经创建的Reader对象,并将下一个读取目标设置为io.Reader类型的参数r,从而达到复用的目的。在需要解压多个文件的时候避免内存分配,提高效率。 - 调用结束后使用
Close()方法回收Reader对象。
压缩/Writer
type Writer struct {
Header // written at first call to Write, Flush, or Close
w io.Writer
level int
wroteHeader bool
compressor *flate.Writer
digest uint32 // CRC-32, IEEE polynomial (section 8)
size uint32 // Uncompressed size (section 2.3.1)
closed bool
buf [10]byte
err error
}
func NewWriter(w io.Writer) *Writer
func NewWriterLevel(w io.Writer, level int) (*Writer, error)
func (z *Writer) Reset(w io.Writer)
func (z *Writer) Write(p []byte) (int, error)
func (z *Writer) Flush() error
func (z *Writer) Close() error
NewWrite()方法创建并返回一个Writer类型的对象的指针,使用默认的压缩级别DefaultCompression,需要压缩的输入流都需要传入该指针。NewWriterLevel()方法可以指定压缩级别,参数level可以是DefaultCompression、NoCompression或BestSpeed与BestCompression。Write()方法可能不一定会立即将压缩的输入写入到文件中,必要时使用Flush()来讲缓冲区中的数据刷入文件。
Example
func compress(file string, gzipWriter gzip.Writer) {
readFile, err := os.Open(file)
if err != nil {
log.Fatal(err)
}
reader := bufio.NewReader(readFile)
for {
s, e := reader.ReadString('\n')
if e == io.EOF {
break
}
_, err := gzipWriter.Write([]byte(s))
if err != nil {
log.Fatal(err)
}
}
}
func deCompress(src, dst string) {
gzipFile, err := os.Open(src)
if err != nil {
log.Fatal(err)
}
gzipReader, err := gzip.NewReader(gzipFile)
if err == io.EOF {
return
}
defer gzipReader.Close()
outfileWriter, err := os.Create(dst)
if err != nil {
log.Fatal(err)
}
defer outfileWriter.Close()
_, err = io.Copy(outfileWriter, gzipReader)
if err != nil {
log.Fatal(err)
}
}