go优雅读取zip压缩包

【需求】 读取压缩包里的指定文件内容,并输出

【解决方法】 遍历循环 -> 内存地址读取

常见方法-循环遍历


/*
*  @Description: 遍历-从压缩包中,提取指定文件的内容,效率较低,易出现内存泄露问题
*  @param archivePath 压缩包路径
*  @param fileName 文件路径 例如www/wwwxxx/11.php
*  @return []byte
*  @return error
 */
func extractFileFromArchive(archivePath, fileName string) ([]byte, error) {
    // 打开压缩文件
    archive, err := os.Open(archivePath)
    if err != nil {
       return nil, err
    }
    defer archive.Close()

    // gzip读取
    gzipReader, err := gzip.NewReader(archive)
    if err != nil {
       return nil, err
    }
    defer gzipReader.Close()

    // tar读取
    tarReader := tar.NewReader(gzipReader)

    // 修复一些读取文件内容错乱
    for {
       header, err := tarReader.Next()
       if err == io.EOF {
          break
       }
       if err != nil {
          return nil, err
       }
       if header.Name == filenameStr && (header.Typeflag == tar.TypeReg || header.Typeflag == tar.TypeRegA) {
          // 找到目标文件,读取内容
          fileContent, err := ioutil.ReadAll(tarReader)
          if err != nil {
             return nil, err
          }
          fmt.Printf("===读取到文件【%s】的内容【%s】\n", fileContent)
          return fileContent, nil
       }
    }
    // 未找到目标文件
    return nil, errors.New("文件不存在")
}

        这种会出现一个问题,如果站点文件极多的情况下,内存会溢出,而且扫描速度很慢,都是秒级的,效率太慢了。

【改进方法】采用map存储压缩包的文件内存地址,需要查询的时候,就直接定位文件内存地址即可读取相关内容

这种方法的核心逻辑如下:

  • 打开压缩包之后。把所有的内存地址丢到一个map中,只需要遍历一次,然后直接调用

var (
    FileOPen = make(map[string]*zip.File, 0)
)
func BuildIndex(zipFilename string) error {
    // Open the zip file
    r, err := zip.OpenReader(zipFilename)
    if err != nil {
       return err
    }
    for _, f := range r.File {
       FileOPen[f.Name] = f
    }
    return nil
}

func main() {
    zipFilename := "/www/wwwroot/222.zip"
    err := BuildIndex(zipFilename)
    if err != nil {
       fmt.Println("Error building index:", err)
       panic(err)
    }
    open, _ := FileOPen["xxx.com/static/app/yyy/aa/src/iiii/xx.js"].Open()
    // 读取文件内容
    rc, err := open.Open()
    if err != nil {
        return nil, err
    }
    data, err := ioutil.ReadAll(rc)
    if err != nil {
       return
    }
    fmt.Println(string(data))
}

【最终效果】 读取文件控制到ms级,相对于循环遍历来说,效率快的太多了

相关推荐

  1. go优雅读取zip压缩

    2024-03-25 11:46:02       42 阅读
  2. 【linux】压缩管理-ZIP

    2024-03-25 11:46:02       54 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-25 11:46:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-25 11:46:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-25 11:46:02       82 阅读
  4. Python语言-面向对象

    2024-03-25 11:46:02       91 阅读

热门阅读

  1. 快速部署一个devops平台onnedev

    2024-03-25 11:46:02       33 阅读
  2. npm中的版本号管理与特殊版本标签深度解析

    2024-03-25 11:46:02       33 阅读
  3. 大模型日报2024-03-24

    2024-03-25 11:46:02       44 阅读
  4. 并发容器之ConcurrentMap

    2024-03-25 11:46:02       36 阅读
  5. 深入理解Python中的集成方法:Boosting

    2024-03-25 11:46:02       44 阅读
  6. (第75天)AutoUpgrade 升级:11GR2 到 19C

    2024-03-25 11:46:02       41 阅读
  7. Redis学习三--集群部分概念

    2024-03-25 11:46:02       36 阅读