ZIP文件实战指南:读写操作一网打尽

简介: ZIP文件实战指南:读写操作一网打尽

1. zip 压缩文件

压缩文件是将一个或多个文件或目录打包成一个文件,以减小存储空间和便于传输。它通过消除冗余信息和使用压缩算法来实现这一目标。

ZIP 是一种常见的压缩文件格式,它不仅在 Windows 环境中得到广泛应用,而且在跨平台的应用中也非常流行。

Go 语言提供了内置的archive/zip标准库,方便进行行 ZIP 文件的创建、读取和解压缩操作。


 

2. 创建和写入 zip 文件

2.1 使用 archive/zip 标准库

Go 语言的 archive/zip 标准库提供了创建和读取 ZIP 文件的功能。


package main
import (  "archive/zip"  "fmt"  "os")

2.2 设置压缩方法 (Store/Deflate)

在创建 ZIP 文件之前,需设置压缩方法。archive/zip 库支持两种主要的压缩方法:zip.Storezip.Deflate

zip.Store 表示不使用压缩,而 zip.Deflate 表示使用 DEFLATE 算法进行压缩。


const zipFileName = "example.zip"
func createZipFile() error {  file, err := os.Create(zipFileName)  if err != nil {    return err  }  defer file.Close()
  zipWriter := zip.NewWriter(file)  defer zipWriter.Close()

2.3 调用 Write()添加文件

创建了 ZIP 文件,接下来可调用 Write 方法向 ZIP 文件中添加文件。


func addFileToZip(zipWriter *zip.Writer, filePath string) error {  // 打开待压缩的文件  fileToZip, err := os.Open(filePath)  if err != nil {    return err  }  defer fileToZip.Close()
  // 创建zip文件中的文件头  fileInfo, err := fileToZip.Stat()  if err != nil {    return err  }  header, err := zip.FileInfoHeader(fileInfo)  if err != nil {    return err  }
  // 使用文件头创建zip文件中的文件  writer, err := zipWriter.CreateHeader(header)  if err != nil {    return err  }
  // 将文件内容写入zip文件  _, err = io.Copy(writer, fileToZip)  return err}

2.4 参数控制压缩级别

通过调整 zip.NewWriterLevel 参数,可以控制压缩级别。

0 表示不压缩,1 表示最低级别,9 表示最高级别。


func createZipFileWithOptions() error {  zipFile, err := os.Create("example.zip")  if err != nil {    return err  }  defer zipFile.Close()
  // 创建zip写入器,设置压缩级别(0-9,0表示不压缩,9表示最高压缩)  zipWriter, err := zip.NewWriterLevel(zipFile, 9)  if err != nil {    return err  }  defer zipWriter.Close()
  // 这里添加文件到zip文件中  return nil}


 

3. 读取和解压 zip

3.1 使用 OpenReader() 打开

除了创建 ZIP 文件,还需要能够读取和解压 ZIP 文件。使用 archive/zip 库的 OpenReader 函数可以打开一个 ZIP 文件供读取。


func readZipFile() error {  zipReader, err := zip.OpenReader(zipFileName)  if err != nil {    return err  }  defer zipReader.Close()

3.2 遍历读取文件信息

通过遍历zipReader.File可以获取 ZIP 文件中的所有文件信息。


func printFileInfo(zipReader *zip.Reader) {  for _, file := range zipReader.File {    fmt.Println("File:", file.Name)    fmt.Println("Compressed Size:", file.CompressedSize)    fmt.Println("Uncompressed Size:", file.UncompressedSize)  }}

3.3 Create()恢复文件内容

可以通过 zip.FileOpen 方法打开文件,然后读取其中的内容。


func extractFile(zipReader *zip.Reader, fileName string) error {  for _, file := range zipReader.File {    if file.Name == fileName {      reader, err := file.Open()      if err != nil {        return err      }      defer reader.Close()
      // 读取文件内容      content, err := ioutil.ReadAll(reader)      if err != nil {        return err      }
      // 处理文件内容      fmt.Println("Content of", fileName, ":", string(content))      return nil    }  }  return fmt.Errorf("File not found: %s", fileName)}

3.4 设置文件属性等元信息

在解压文件时,可设置文件的一些属性,例如权限等。


func setFileAttributes(file *zip.File) {  file.SetMode(os.FileMode(0755)) // 设置文件权限}


 

4. 并发压缩和解压

4.1 通过 goroutine 并发处理

使用 goroutine 可以提高 zip 文件的压缩和解压速度,特别是在处理大文件或多个文件时。



func concurrentZip(files []string) {  var wg sync.WaitGroup
  for _, file := range files {    wg.Add(1)    go func(fileName string) {      defer wg.Done()      err := addFileToZip(zipWriter, fileName)      if err != nil {        fmt.Println("Error adding file to ZIP:", err)      }    }(file)  }
  wg.Wait()}

4.2 提高大文件多文件的压缩速度

在并发处理中,需要注意避免资源竞争,特别是在写入 ZIP 文件时。


var mu sync.Mutex
func addFileToZipConcurrent(zipWriter *zip.Writer, fileName string) {  fileToZip, err := os.Open(fileName)  if err != nil {    fmt.Println("Error opening file:", err)    return  }  defer fileToZip.Close()
  info, err := fileToZip.Stat()  if err != nil {    fmt.Println("Error getting file info:", err)    return  }
  header, err := zip.FileInfoHeader(info)  if err != nil {    fmt.Println("Error creating file header:", err)    return  }
  header.Name = fileName  header.Method = zip.Deflate
  mu.Lock()  writer, err := zipWriter.CreateHeader(header)  mu.Unlock()
  if err != nil {    fmt.Println("Error creating file in ZIP:", err)    return  }
  _, err = io.Copy(writer, fileToZip)    if err != nil {    fmt.Println("Error copying file to ZIP:", err)  }}


 

5. 压缩加密与分割

5.1 SetPassword()进行加密

通过使用 SetPassword 方法,可给 ZIP 文件添加密码。


func encryptZipFile() error {  file, err := os.Create("encrypted.zip")  if err != nil {    return err  }  defer file.Close()
  zipWriter := zip.NewWriter(file)  defer zipWriter.Close()
  zipWriter.SetPassword("securepassword")  err = addFileToZip(zipWriter, "file.txt")  return err}

5.2 MultiWriter()分卷存储

有的时候,需将大文件分割成多个卷存储,以便于传输和存储。


func splitLargeFile(fileName string, chunkSize int64) error {  file, err := os.Open(fileName)  if err != nil {    return err  }  defer file.Close()
  fileInfo, err := file.Stat()  if err != nil {    return err  }
  // 计算分卷数量  numChunks := (fileInfo.Size() + chunkSize - 1) / chunkSize
  for i := int64(0); i < numChunks; i++ {    partFileName := fmt.Sprintf("part%d.zip", i+1)    partFile, err := os.Create(partFileName)    if err != nil {      return err    }    defer partFile.Close()
    // 创建分卷zip.Writer    zipWriter := zip.NewWriter(partFile)    defer zipWriter.Close()
    // 将文件分卷写入zip.Writer    _, err = io.CopyN(zipWriter, file, chunkSize)    if err != nil && err != io.EOF {      return err    }  }  return nil}

5.3 设置相关可选参数

zip.Writer 提供了一些可选参数,例如 CommentExtra,用于设置 ZIP 文件的注释和额外信息。


func setZipFileOptions() error {  file, err := os.Create("options.zip")  if err != nil {    return err  }  defer file.Close()
  zipWriter := zip.NewWriter(file)  defer zipWriter.Close()
  // 设置注释和额外信息  zipWriter.Comment = "This is a ZIP file with options"  zipWriter.Extra = []byte("Optional extra information")
  err = addFileToZip(zipWriter, "file.txt")  return err}


 

6. 使用建议

6.1 检查文件关闭与错误

在进行文件操作时,务必检查文件的关闭和错误处理,以避免资源泄漏和程序异常。


func main() {  err := createZipFile()  if err != nil {    fmt.Println("Error creating ZIP file:", err)  }
  err = readZipFile()  if err != nil {    fmt.Println("Error reading ZIP file:", err)  }}

6.2 优化内存占用

对于大文件的处理,可以通过逐块读取、写入,以及合理使用缓冲区,来降低内存占用。

6.3 自定义元信息

可以通过自定义元信息来附加额外的信息到 zip 文件,以便在解压时获取


zipWriter.SetComment("This is a custom comment.")


 

总结

通过 archive/zip 标准库,Go 语言提供了强大而灵活的 zip 文件读写功能。

无论是创建、读取、解压,还是加密、并发处理,都可以轻松应对各种需求。

合理的使用可选参数和并发处理,能够进一步提高程序的性能和效率。希望本文能够帮助读者更好地理解和使用 Go 语言进行 zip 文件的读写操作。

目录
相关文章
|
5月前
|
Java API 数据处理
Java文件操作,让你成为文件管理的王者!读写、复制、删除不在话下!
【6月更文挑战第27天】在Java编程中,掌握文件操作至关重要。使用java.io包的File和流类,可以轻松实现文件读写、复制和删除。
50 0
|
6月前
|
Linux 网络安全 数据处理
【专栏】Linux下的xxd命令是一个强大的二进制数据处理工具,用于十六进制转储和数据分析,我教你应该如何使用!
【4月更文挑战第28天】Linux下的xxd命令是一个强大的二进制数据处理工具,用于十六进制转储和数据分析。它可以显示文件的十六进制和ASCII表示,方便查看内容、分析数据结构和比较文件。xxd支持指定输出格式、写入文件、数据提取和转换等功能。在网络安全分析、程序调试和数据恢复等领域有广泛应用。通过掌握xxd,用户能更深入理解和处理二进制数据。
825 0
|
6月前
|
存储 安全 Linux
【Linux 创建临时文件 API】编程中的瞬息之光:临时文件的艺术与智慧 tmpnam,tmpfile,mkstemp,mkdtemp等函数解析...
【Linux 创建临时文件 API】编程中的瞬息之光:临时文件的艺术与智慧 tmpnam,tmpfile,mkstemp,mkdtemp等函数解析...
112 0
|
Shell Perl
Shell基础学习---4、文本处理工具、综合应用案例(归档文件、发送信息)
Shell基础学习---4、文本处理工具、综合应用案例(归档文件、发送信息)
|
存储 关系型数据库 MySQL
【C-文件操作】一文教你如何将代码的数据持久化(一)
【C-文件操作】一文教你如何将代码的数据持久化
114 0
【C-文件操作】一文教你如何将代码的数据持久化(一)
|
存储
【C-文件操作】一文教你如何将代码的数据持久化(二)
【C-文件操作】一文教你如何将代码的数据持久化
132 0
【C-文件操作】一文教你如何将代码的数据持久化(二)
|
开发工具 Android开发 git
竟然有如此好用的读Android源码利器
竟然有如此好用的读Android源码利器
竟然有如此好用的读Android源码利器
|
C# Windows
☀️ 学会编程入门必备 C# 最基础知识介绍—— C# 高级文件操作(文本文件的读写、二进制文件的读写、Windows 文件系统的操作)
前言🙏 C# 文本文件的读写👇 StreamWriter 类 C# 二进制文件的读写👏 BinaryReader 类 BinaryWriter 类 C# Windows 文件系统的操作👋 DirectoryInfo 类 FileInfo 类
☀️ 学会编程入门必备 C# 最基础知识介绍—— C# 高级文件操作(文本文件的读写、二进制文件的读写、Windows 文件系统的操作)
|
开发者 Python
文件的读写 | 手把手教你入门Python之七十
使⽤write()可以完成向⽂件写⼊数据,使⽤read(num)可以从⽂件中读取数据,num表示要从⽂件中读取的数据的⻓度(单位是字节),如果没有传⼊num,那么就表示读取⽂件中所有的数据
文件的读写 | 手把手教你入门Python之七十
|
分布式计算 大数据 Linux
Spark修炼之道(基础篇)——Linux大数据开发基础:第二节:Linux文件系统、目录(一)
本节主要内容 如何获取帮助文档 Linux文件系统简介 目录操作 访问权限 1. 如何获取帮助文档 在实际工作过程当中,经常会忘记命令的使用方式,例如ls命令后面可以跟哪些参数,此时可以使用man命令来查看其使用方式,例如 //man命令获取命令帮助手册 xtwy@ubuntu:~$ man ls 可以使用键盘上的 来显示下一行或上一行命令,也可以使用
3450 0