最近在收java课作业的时候,实在懒得一个一个人解压,收作业真的是很麻烦的事,所以想做一个作业提交平台挂到服务器上,实现自动解压自动保存,再一键整合压缩交给老师,所以研究了一下使用go操作文件压缩与解压缩的方式。
压缩
参数
- dirToZip:想要压缩的文件,例如./test,即为压缩test目录下的所有文件
- zipFilePath:想要压缩的文件路径及压缩后的文件名,例如./totest/test.zip,即为压缩到totest路径下,命名为test.zip
func tozip(dirToZip string, zipFilePath string) error {
// 创建一个新的 ZIP 文件
zipFile, err := os.Create(zipFilePath)
if err != nil {
panic(err)
}
defer zipFile.Close()
// 创建一个 ZIP 格式的写入器
zipWriter := zip.NewWriter(zipFile)
defer zipWriter.Close()
// 遍历目录及其子目录中的所有文件并将它们添加到 ZIP 文件中
filepath.Walk(dirToZip, func(path string, info os.FileInfo, err error) error {
// 如果访问文件或目录时出现错误,直接返回错误
if err != nil {
return err
}
// 获取相对路径
relPath, err := filepath.Rel(dirToZip, path)
if err != nil {
return err
}
// 如果当前路径是目录,则创建一个新的目录头并添加到 ZIP 文件中
if info.IsDir() {
header := zip.FileHeader{
Name: relPath + "/",
Method: zip.Store,
}
_, err = zipWriter.CreateHeader(&header)
if err != nil {
return err
}
return nil
}
// 如果当前路径是文件,则创建一个新的文件头并将文件内容添加到 ZIP 文件中
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
header := zip.FileHeader{
Name: relPath,
Method: zip.Deflate,
}
writer, err := zipWriter.CreateHeader(&header)
if err != nil {
return err
}
_, err = io.Copy(writer, file)
if err != nil {
return err
}
return nil
})
fmt.Println("压缩完成:", zipFilePath)
return err
}
解压缩
参数
- src:需要解压的具体文件,例如./test/test.zip。
- dest:解压后保存的路径,例如./test/user,会把文件解压缩到user目录里。
func unzip(src string, dest string) error {
r, err := zip.OpenReader(src) //打开文件
if err != nil {
return err
}
defer r.Close()
var decodeName string
for _, f := range r.File {
rc, err := f.Open()
if err != nil {
return err
}
defer rc.Close()
//gbkBytes, err := simplifiedchinese.GBK.NewEncoder().Bytes([]byte(f.Name))
//filename := string(gbkBytes)
if f.Flags == 0 {
//如果标致位是0 则是默认的本地编码 默认为gbk
i := bytes.NewReader([]byte(f.Name))
decoder := transform.NewReader(i, simplifiedchinese.GB18030.NewDecoder())
content, _ := io.ReadAll(decoder)
decodeName = string(content)
} else {
//如果标志为是 1 << 11也就是 2048 则是utf-8编码
decodeName = f.Name
}
path := filepath.Join(dest, decodeName) //拿到文件的路径信息
fmt.Println(f.Name)
if !strings.HasPrefix(path, filepath.Clean(dest)+string(os.PathSeparator)) {
return fmt.Errorf("%s: illegal file path", path)
}
if f.FileInfo().IsDir() {
os.MkdirAll(path, f.Mode())
} else {
os.MkdirAll(filepath.Dir(path), f.Mode()) //创建文件的父目录
outFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) //创建文件
/*os.O_WRONLY表示以只写模式打开文件;
os.O_CREATE表示如果文件不存在则创建文件;
os.O_TRUNC表示如果文件存在则清空文件。*/
if err != nil {
return err
}
defer outFile.Close()
_, err = io.Copy(outFile, rc) //将读取到的内容写入这个文件
if err != nil {
return err
}
}
}
return nil
}