Go 和许多其他编程语言一样,支持从标准库中直接进行 zip 文件的压缩和解压。在 Go 中利用标准库包 archive/zip 完成 zip 文件的创建和提取。golang zip包的解压有官方的zip包(archive/zip),但是官方给的zip解压包代码只有解压不带密码的zip包,如果我们要解压带密码的zip就做不了, 解决方案:使用 github.com/yeka/zip。
文章目录 一、压缩操作1.1 第一步:创建一个 zip 基础文件1.2 第二步:初始化 zip.Writer1.3 第三步:使用 zip.Writer.Create创建一个 io.Writer1.4 第四步:使用 io.Copy或 io.Writer.Write 写数据到到 zip 文件1.5 第五步:使用 zip.Writer.Close 关闭 zip 文件1.6 压缩无密码zip包(源码案例) 二、解压操作2.1 第一步:使用 zip.OpenReader 打开 zip 文件2.2 第二步:循环访问 zip 中的文件2.3 第三步:使用 zip.File.Open方法读取 zip 中文件的内容2.4 第四步:使用 io.Copy 或 io.Writer.Write 保存解压后的文件内容**2.5 第五步:使用 zip.Reader.Close 关闭 zip 文件**2.6 解压不带密码zip压缩包(源码案例) 三、针对带密码的zip操作3.1 解压带密码zip压缩包3.2 解压带密码zip压缩包(源码案例) 一、压缩操作 1.1 第一步:创建一个 zip 基础文件zip 文件也是一个文件,我们要做的第一件事是创建为一个简单的文件作为 zip 文件,就像在 Go 中处理任何其他文件一样。使用 os 第三方包的 os.Create() 函数创建一个文件对象。
func Create(name string) (*File, error) 1.2 第二步:初始化 zip.Writer使用 archive/zip包中的 zip.NewWriter 函数初始化一个 zip.Writer,用于将数据(文件和目录)写入 zip 文件。
func NewWriter(w io.Writer) *Writer 1.3 第三步:使用 zip.Writer.Create创建一个 io.Writer一旦创建完 zip writer 后,便可以使用 zip.Writer.Create 向 zip 文件中添加一个文件或目录。它返回一个待压缩的文件内容应写入的 Writer,文件内容将使用 Deflate 方法进行压缩。
func (w *Writer) Create(name string) (io.Writer, error) 1.4 第四步:使用 io.Copy或 io.Writer.Write 写数据到到 zip 文件zip.Writer.Create 函数返回一个 io.Writer ,因此任何文件内容都可以通过流式写入该 writer。使用 io.Copy 或调用 writer 的 Write 方法。
func Copy(dst Writer, src Reader) (written int64, err error) 1.5 第五步:使用 zip.Writer.Close 关闭 zip 文件将所有文件和目录写入 zip 文件后,可以通过 zip.Writer.Close 方法关闭 zip writer,将所有数据写入指向基础 zip 文件的数据流。注意,它不会关闭指向基础 zip 文件的 Writer。
func (w *Writer) Close() error 1.6 压缩无密码zip包(源码案例) package mainimport ("archive/zip""fmt""io""os")func main_zip_file() {fmt.Println("creating zip archive...")// 1、创建 zip 基础文件archive, err := os.Create("D:\CODEFile01\GoPro\unZipPro\src\data\archive.zip")if err != nil {panic(err)}defer archive.Close()// 2、初始化zip写入对象zipWriter := zip.NewWriter(archive)fmt.Println("opening first file...")f1, err := os.Open("D:\CODEFile01\GoPro\unZipPro\src\data\test.csv")if err != nil {panic(err)}defer f1.Close()fmt.Println("writing first file to archive...")// 3、使用 zip.Writer.Create 创建一个 io.Writer,使用Create() 向zip文件中添加一个文件或目录w1, err := zipWriter.Create("test.csv")if err != nil {panic(err)}// 4、使用 io.Copy 或 io.Writer.Write 写数据到到zip文件if _, err := io.Copy(w1, f1); err != nil {panic(err)}fmt.Println("opening second file...")f2, err := os.Open("D:\CODEFile01\GoPro\unZipPro\src\data\test.txt")if err != nil {panic(err)}defer f2.Close()fmt.Println("writing second file to archive...")w2, err := zipWriter.Create("test.txt")if err != nil {panic(err)}if _, err := io.Copy(w2, f2); err != nil {panic(err)}fmt.Println("closing zip archive...")// 5、使用 zip.Writer.Close 关闭 zip 文件zipWriter.Close()} 二、解压操作 2.1 第一步:使用 zip.OpenReader 打开 zip 文件要想解压 zip 文件我们可能需要做的第一件事是打开它。我们可以使用 archive/zip 包提供的函数 zip.OpenReader 来打开 zip 文件,以 io.ReadCloser 的形式返回一个 zip.Reader 的实例。
func OpenReader(name string) (*ReadCloser, error) 2.2 第二步:循环访问 zip 中的文件zip.OpenReader 返回一个 zip.Reader 实例,其包含一个 zip.File 切片。
type Reader struct { File []*File Comment string // contains filtered or unexported fields 2.3 第三步:使用 zip.File.Open方法读取 zip 中文件的内容 func (f *File) Open() (io.ReadCloser, error) 2.4 第四步:使用 io.Copy 或 io.Writer.Write 保存解压后的文件内容** func Copy(dst Writer, src Reader) (written int64, err error) 2.5 第五步:使用 zip.Reader.Close 关闭 zip 文件**读取完 zip 存档中所有文件的内容并保存到指定位置后,要用接口 ReadCloser 中的方法 Close 关闭文件句柄。
type ReadCloser interface { Reader Closer } // Closer is the interface that wraps the basic Close method. // The behavior of Close after the first call is undefined. // Specific implementations may document their own behavior. type Closer interface { Close() error } 2.6 解压不带密码zip压缩包(源码案例) package mainimport ("archive/zip""fmt""io""os""path/filepath""strings")func main() {dst := "D:\CODEFile01\GoPro\unZipPro\src\data_output"// 1、使用zip.OpenReader打开zip文件archive, err := zip.OpenReader("D:\CODEFile01\GoPro\unZipPro\src\data\DYSH_20230104_Index.zip")if err != nil {panic(err)}defer archive.Close()// 2、循环访问 zip 中的文件 zip.File 切片for _, f := range archive.File {filePath := filepath.Join(dst, f.Name)fmt.Println("unzipping file ", filePath)if !strings.HasPrefix(filePath, filepath.Clean(dst)+string(os.PathSeparator)) {fmt.Println("invalid file path")return}if f.FileInfo().IsDir() {fmt.Println("creating directory...")os.MkdirAll(filePath, os.ModePerm)continue}if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {panic(err)}dstFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())if err != nil {panic(err)}// 3、使用 zip.File.Open 方法读取 zip 中文件的内容fileInArchive, err := f.Open()if err != nil {panic(err)}// 4、使用 io.Copy 或 io.Writer.Write 保存解压后的文件内容if _, err := io.Copy(dstFile, fileInArchive); err != nil {panic(err)}// 5、使用 zip.Reader.Close 关闭 zip 文件dstFile.Close()fileInArchive.Close()}} 三、针对带密码的zip操作解决方案:使用 github.com/yeka/zip
3.1 解压带密码zip压缩包关键代码:
if f.IsEncrypted() {f.SetPassword(passwd)}其实就是将go官方zip包 archive/zip做一个替换即可。
3.2 解压带密码zip压缩包(源码案例) package mainimport (//"archive/zip""fmt""io""os""path/filepath""strings""github.com/yeka/zip")func main() {dst := "D:\CODEFile01\GoPro\unZipPro\src\data_output"passwd := "DataYes"// 1、使用zip.OpenReader打开zip文件archive, err := zip.OpenReader("D:\CODEFile01\GoPro\unZipPro\src\data\DYSH_20230104_Index.zip")if err != nil {panic(err)}defer archive.Close()// 2、循环访问 zip 中的文件 zip.File 切片for _, f := range archive.File {if f.IsEncrypted() {f.SetPassword(passwd)}filePath := filepath.Join(dst, f.Name)fmt.Println("unzipping file ", filePath)if !strings.HasPrefix(filePath, filepath.Clean(dst)+string(os.PathSeparator)) {fmt.Println("invalid file path")return}if f.FileInfo().IsDir() {fmt.Println("creating directory...")os.MkdirAll(filePath, os.ModePerm)continue}if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {panic(err)}dstFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())if err != nil {panic(err)}// 3、使用 zip.File.Open 方法读取 zip 中文件的内容fileInArchive, err := f.Open()if err != nil {panic(err)}// 4、使用 io.Copy 或 io.Writer.Write 保存解压后的文件内容if _, err := io.Copy(dstFile, fileInArchive); err != nil {panic(err)}// 5、使用 zip.Reader.Close 关闭 zip 文件dstFile.Close()fileInArchive.Close()}}以上便是针对带密码的zip压缩包解压方法!!!