Golang zip流式解析器

文章介绍了Golang标准库archive/zip的NewReader方法,它需要一个io.ReaderAt和文件大小作为参数,而第三方库zipiterator提供了一个仅需io.Reader的NewReader方法,简化了使用。zipiterator允许顺序读取但不支持并发,适合特定场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Golang标准库 archive/zip 提供了对zip压缩包的解析功能,主要的NewReader方法签名为:

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

需要提供一个比较特别的 io.ReaderAt 参数,另外还要提供文件大小。
基本的使用方法:

func main() {

   f, err := os.Open("demo.zip")
   if err != nil {
      log.Fatal(err)
   }
   defer f.Close()

   stat, err := f.Stat()
   if err != nil {
      log.Fatal(err)
   }

   r, err := zip.NewReader(f, stat.Size())
   if err != nil {
      log.Fatal(err)
   }

   for _, z := range r.File {
      log.Println("file name:", z.Name)
      zf, err := z.Open()
      if err != nil {
         continue
      }
      io.ReadAll(zf)
      zf.Close()
   }
}

这和其他类似的NewReader方法签名有很大差别,比如说 archive/tarcompress/bzip2compress/flatecompress/gzipcompress/zlib
等包中的 NewReader 方法基本只需要一个普通的 io.Reader参数,如果有一个zip包也只需要 io.Reader,则可以让这些解压缩方法保持一致性。

作为替代品,我们可以使用这个库 https://github.com/zhyee/zipiterator,提供的NewReader 方法为:

func NewReader(r io.Reader) *Reader

使用示例:

package main

import (
  "io"
  "log"
  "os"

  "github.com/zhyee/zipiterator"
)

func main() {

  f, err := os.Open("demo.zip")
  if err != nil {
     log.Fatal(err)
  }
  defer f.Close()

  zr := zipiterator.NewReader(f)

  for {
     e, err := zr.GetNextEntry()
     if err == io.EOF {
        break
     }
     if err != nil {
        log.Fatalf("unable to get next entry: %s", err)
     }

     log.Println("entry name: ", e.Name)
     log.Println("entry comment: ", e.Comment)
     log.Println("entry reader version: ", e.ReaderVersion)
     log.Println("entry modify time: ", e.Modified)
     log.Println("entry compressed size: ", e.CompressedSize64)
     log.Println("entry uncompressed size: ", e.UncompressedSize64)
     log.Println("entry is a dir: ", e.IsDir())

     if !e.IsDir() {
        rc, err := e.Open()
        if err != nil {
           log.Fatalf("unable to open zip file: %s", err)
        }
        content, err := io.ReadAll(rc)
        if err != nil {
           log.Fatalf("read zip file content fail: %s", err)
        }

        log.Println(string(content))

        if uint64(len(content)) != e.UncompressedSize64 {
           log.Fatalf("read zip file length not equal with UncompressedSize64")
        }
        if err := rc.Close(); err != nil {
           log.Fatalf("close zip entry reader fail: %s", err)
        }
     }
  }
}

当然,该包也存在一些限制,比如只能顺序读取,不支持并发读取等等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值