golang基础(golang压缩文件gzip)

来源:互联网 发布:win10视频剪辑软件 编辑:程序博客网 时间:2024/06/07 09:48

前言

曾经,因为不够注重基础吃了好多亏。总是很喜欢去看那些高大上的东西,却忽略了最基本的东西。然后会错误的以为自己懂的很多,但是其实是沙堆中筑高台,知道很多高大上的架构,但是基础的东西却不太了解。我觉得,可能这就是大部分开发工程师的通病吧。

正题

在软件很多应用开发过程中,经常需要使用到文件压缩。有时候是为了加快存盘速度,有时候是为了节省硬盘空间,有时候是为了提高传输效率。gzip是一种比较通用的压缩程序,golang系统自带的包里边compress/gzip就可以实现在代码中实现gzip的功能。

一、compress/gzip包的用法
先看看compress/gzip包中的测试用例:

func Example_writerReader() {    var buf bytes.Buffer    zw := gzip.NewWriter(&buf)    // Setting the Header fields is optional.    zw.Name = "a-new-hope.txt"    zw.Comment = "an epic space opera by George Lucas"    zw.ModTime = time.Date(1977, time.May, 25, 0, 0, 0, 0, time.UTC)    _, err := zw.Write([]byte("A long time ago in a galaxy far, far away..."))    if err != nil {        log.Fatal(err)    }    if err := zw.Close(); err != nil {        log.Fatal(err)    }    zr, err := gzip.NewReader(&buf)    if err != nil {        log.Fatal(err)    }    fmt.Printf("Name: %s\nComment: %s\nModTime: %s\n\n", zr.Name, zr.Comment, zr.ModTime.UTC())    if _, err := io.Copy(os.Stdout, zr); err != nil {        log.Fatal(err)    }    if err := zr.Close(); err != nil {        log.Fatal(err)    }    // Output:    // Name: a-new-hope.txt    // Comment: an epic space opera by George Lucas    // ModTime: 1977-05-25 00:00:00 +0000 UTC    //    // A long time ago in a galaxy far, far away...}

方法说明
1、func NewWriter(w io.Writer) *Writer
NewWriter返回一个Writer接口,调用Writer的write方法把数据压缩后写入w。并由调用者负责关闭接口,有另外一个创建Writer的接口func NewWriterLevel(w io.Writer, level int) (*Writer, error) 其使用方法和NewWriter一样,就是增加了一个压缩级别。压缩级别和gzipgzip的压缩级别定义一致。具体可以看每天回顾linux命令(gzip) 中对压缩效率的介绍。
2、func NewReader(r io.Reader) (*Reader, error)
NewReader创建一个新的Reader接口,并且将Reader的内容赋值为r,压缩数据存储在r中,并由调用者负责关闭接口。

Writer接口方法介绍
1、func (z *Writer) Close() error
关闭Writer接口,但是不关闭创建接口是引入的io.Writer。
2、func (z *Writer) Flush() error
把缓存中的数据刷到初始化时候传入的io.Writer中。注意,这个操作是个阻塞操作。
3、func (z *Writer) Reset(w io.Writer)
刷新Writer的状态为初始状态,并更替其内部的io.Writer
4、func (z *Writer) Write(p []byte) (int, error)
把p的内容压缩后写入接口实例内部的io.Writer中。支持多次写入,后面写入的拼接在先写入的后面。

Reader接口方法介绍
1、func (z *Reader) Close() error
关闭Reader接口,但是不关闭创建接口是引入的io.Reader。
2、func (z *Reader) Multistream(ok bool)
设置Reader接口是否支持多流。
3、func (z *Reader) Read(p []byte) (n int, err error)
将io.Reader内容部分的内容解压后复制到p。
4、func (z *Reader) Reset(r io.Reader) error
刷新Reader的状态为初始状态,并更替其内部的io.Reader

文件压缩实例

定义解压缩文件接口CompressFile和DeCompressFile:
gziptest.go:

package gziptestimport (    "compress/gzip"    "io"    "os")//压缩文件Src到Dstfunc CompressFile(Dst string, Src string) error {    newfile, err := os.Create(Dst)    if err != nil {        return err    }    defer newfile.Close()    file, err := os.Open(Src)    if err != nil {        return err    }    zw := gzip.NewWriter(newfile)    filestat, err := file.Stat()    if err != nil {        return nil    }    zw.Name = filestat.Name()    zw.ModTime = filestat.ModTime()    _, err = io.Copy(zw, file)    if err != nil {        return nil    }    zw.Flush()    if err := zw.Close(); err != nil {        return nil    }    return nil}//解压文件Src到Dstfunc DeCompressFile(Dst string, Src string) error {    file, err := os.Open(Src)    if err != nil {        panic(err)    }    defer file.Close()    newfile, err := os.Create(Dst)    if err != nil {        panic(err)    }    defer newfile.Close()    zr, err := gzip.NewReader(file)    if err != nil {        panic(err)    }    filestat, err := file.Stat()    if err != nil {        panic(err)    }    zr.Name = filestat.Name()    zr.ModTime = filestat.ModTime()    _, err = io.Copy(newfile, zr)    if err != nil {        panic(err)    }    if err := zr.Close(); err != nil {        panic(err)    }    return nil}

单元测试用例:
gziptest_test.go

package gziptestimport (    "os"    "testing")func TestCompressFile(t *testing.T) {    pwd, _ := os.Getwd()    newfile, err := os.Create(pwd + "/test.txt")    if err != nil {        t.Fatal(err)    }    newfile.Write([]byte("hello world!!!!"))    newfile.Close()    err = CompressFile(pwd+"/test.gz", pwd+"/test.txt")    if err != nil {        t.Fatal(err)    }}func TestDeCompressFile(t *testing.T) {    pwd, _ := os.Getwd()    err := DeCompressFile(pwd+"/test2.txt", pwd+"/test.gz")    if err != nil {        t.Fatal(err)    }}

测试结果:

C:/Go/bin/go.exe test -v [D:/go/src/gziptest]=== RUN   TestCompressFile--- PASS: TestCompressFile (0.00s)=== RUN   TestDeCompressFile--- PASS: TestDeCompressFile (0.00s)PASSok      gziptest    2.351s

同级目录下增加了三个文件:
其中test.txt和test2.txt内容为:

hello world!!!!

test.gz内容为text.txt