golang代码解压文件并处理文件

        最近项目需求,需要前端页面将压缩文件传递打后台,然后后台再解压文件,对文件进行逐一进行处理。刚开始实现这个技术的时候本来想使用原生的库来进行解压处理,后面想着找找有造好的轮子应该可以拿来用,就在github上进行了搜寻,最后找到一个可以用的轮子,名字为archiver,github地址为:https://github.com/mholt/archiver

1、介绍

       此开源轮子支持rar,zip,7z等压缩格式,其他的压缩格式可以在github上的详情进行查看,因为我目前暂时只需要rar和zip的解压方式,7z格式虽然说是支持,但是我试过,解压的时候会报错,不支持该格式的压缩文件。不知道什么原因,我去issues提过问题,他们也没给个让人明白的答案,仿佛是支持,但是我测试出来是不支持的。因为我只需要解压功能,所以下面我只演示解压的使用方法,压缩的方法可以通过github自行测试研究。

2、使用方法

我测试代码的go版本使用的使用的是1.18.3版本,测试代码如下所示,比较简单,一看就能明白:

package main

import (
	"context"
	"fmt"
	"io"
	"os"
    "github.com/mholt/archiver/v4"
)



func main() {
	ArchiverTest("public.zip")
}


// archiver解压压缩包
func ArchiverTest(path string) {
	f, _ := os.Open(path)
	format, readStream, err := archiver.Identify(path, f)
	if err != nil {
		return
	}
	extractor, ok := format.(archiver.Extractor)
	if !ok {
		return
	}
	switch extractor.(type) {
	case archiver.Zip:
		extractor = archiver.Zip{TextEncoding: "gbk"}
		fmt.Println("archiver.Zip")
	case archiver.SevenZip:
		extractor = archiver.SevenZip{}
		fmt.Println("archiver.SevenZip")
	case archiver.Rar:
		extractor = archiver.Rar{}
		fmt.Println("archiver.Rar")
	default:
		fmt.Println("unsupported compression algorithm")
		return
	}

	//fileList := []string{"file1.txt", "subfolder"}
	ctx := context.Background()
	handler := func(ctx context.Context, f archiver.File) error {
		filename := f.Name()
		newfile, err := os.Create(filename)
		if err != nil {
			panic(err)
		}
		defer newfile.Close()
		old, err := f.Open()
		if err != nil {
			panic(err)
		}
		defer old.Close()
		_, err = io.Copy(newfile, old)

		if err != nil {
			panic(err)
		}
		fmt.Printf("extracted %s \n", f.Name())
		return nil
	}

	err = extractor.Extract(ctx, readStream, nil, handler)
	if err != nil {
		return
	}

}

  • 代码中可以看到通过一个解压函数将压缩文件传入,然后进行解压
  • 传入后,会对传入的压缩文件进行分类,代码中我分为了zip、rar和7z的压缩方式
  • err = extractor.Extract(ctx, readStream, nil, handler)的handler是前面定义的函数,属于回调函数,回调函数是对每一个解压出来的文件进行处理,代码示例中的操作是将压缩文件解压出来,然后保存到本地目录,然后还打印了解压后的文件名字
  • 回调函数是阻塞型的函数,里面没有调用携程来进行处理,所以回调函数要把解压后的所有文件处理完成后,该函数才会返回

3、回调函数参数传递

        如果需要传递参数到回调函数的话,可以使用如下代码进行传递参数:

package main

import (
	"context"
	"fmt"
	"io"
	"os"
    "github.com/mholt/archiver/v4"
)

type jellyString struct{}

func main() {
	ArchiverTest("public.zip")
}


// archiver解压压缩包
func ArchiverTest(path string) {
	f, _ := os.Open(path)
	format, readStream, err := archiver.Identify(path, f)
	if err != nil {
		return
	}
	extractor, ok := format.(archiver.Extractor)
	if !ok {
		return
	}
	switch extractor.(type) {
	case archiver.Zip:
		extractor = archiver.Zip{TextEncoding: "gbk"}
		fmt.Println("archiver.Zip")
	case archiver.SevenZip:
		extractor = archiver.SevenZip{}
		fmt.Println("archiver.SevenZip")
	case archiver.Rar:
		extractor = archiver.Rar{}
		fmt.Println("archiver.Rar")
	default:
		fmt.Println("unsupported compression algorithm")
		return
	}

	//fileList := []string{"file1.txt", "subfolder"}
	handler := func(ctx context.Context, f archiver.File) error {

        inputdata := ctx.Value(jellyString{}).(string)
        fmt.Printf("inputdata %s \n", inputdata )
    
		filename := f.Name()
		newfile, err := os.Create(filename)
		if err != nil {
			panic(err)
		}
		defer newfile.Close()
		old, err := f.Open()
		if err != nil {
			panic(err)
		}
		defer old.Close()
		_, err = io.Copy(newfile, old)

		if err != nil {
			panic(err)
		}
		fmt.Printf("extracted %s \n", f.Name())
		return nil
	}

    username := "传递参数用户名username"
    ctx := context.Background()
    ctxValue := context.WithValue(ctx, jellyString{}, username)
	err = extractor.Extract(ctxValue , readStream, nil, handler)
	if err != nil {
		return
	}

}

传参数用的是一个结构体参数,据说是比较安全的传递参数的方法,我也按照这种建议的方式进行的参数传递,单个参数和结构体参数应该都可以传递。

4、小结

        解压文件我测试后还是可以针对rar和zip进行解压,并完整的将文件保存下来的,7z我测试无法成功,有成功的同学可以评论区分享,我怀疑可能是我go版本过低,没有亲自验证。还有就是如果你需要处文件的代码比较多的话,可以将回调函数写在外面,结构性要更强一些。

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值