commit
This commit is contained in:
+29
@@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
// ...
|
||||
"archive/tar"
|
||||
"compress/gzip" // 这里导入 compress/gzip 包
|
||||
"os"
|
||||
// ...
|
||||
)
|
||||
|
||||
func Tar(src string, dstTar string, failIfExist bool) (err error) {
|
||||
// ...
|
||||
fw, er := os.Create(dstTar)
|
||||
// ...
|
||||
gw := gzip.NewWriter(fw) // 这里添加一个 gzip.Writer
|
||||
// ...
|
||||
tw := tar.NewWriter(gw) // 这里传入 gw
|
||||
// ...
|
||||
}
|
||||
|
||||
func UnTar(srcTar string, dstDir string) (err error) {
|
||||
// ...
|
||||
fr, er := os.Open(srcTar)
|
||||
// ...
|
||||
gr, er := gzip.NewReader(fr) // 这里添加一个 gzip.Reader
|
||||
// ...
|
||||
tr := tar.NewReader(gr) // 这里传入 gr
|
||||
// ...
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
|
||||
func main() {
|
||||
TarFile := "test.tar"
|
||||
src := "test"
|
||||
dstDir := "test_ext"
|
||||
|
||||
if err := Tar(src, TarFile, false); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if err := UnTar(TarFile, dstDir); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
// 将文件或目录打包成 .tar 文件
|
||||
// src 是要打包的文件或目录的路径
|
||||
// dstTar 是要生成的 .tar 文件的路径
|
||||
// failIfExist 标记如果 dstTar 文件存在,是否放弃打包,如果否,则会覆盖已存在的文件
|
||||
func Tar(src string, dstTar string, failIfExist bool) (err error) {
|
||||
// 清理路径字符串
|
||||
src = path.Clean(src)
|
||||
|
||||
// 判断要打包的文件或目录是否存在
|
||||
if !Exists(src) {
|
||||
return errors.New("要打包的文件或目录不存在:" + src)
|
||||
}
|
||||
|
||||
// 判断目标文件是否存在
|
||||
if FileExists(dstTar) {
|
||||
if failIfExist { // 不覆盖已存在的文件
|
||||
return errors.New("目标文件已经存在:" + dstTar)
|
||||
} else { // 覆盖已存在的文件
|
||||
if er := os.Remove(dstTar); er != nil {
|
||||
return er
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 创建空的目标文件
|
||||
fw, er := os.Create(dstTar)
|
||||
if er != nil {
|
||||
return er
|
||||
}
|
||||
defer fw.Close()
|
||||
|
||||
// 创建 tar.Writer,执行打包操作
|
||||
tw := tar.NewWriter(fw)
|
||||
defer func() {
|
||||
// 这里要判断 tw 是否关闭成功,如果关闭失败,则 .tar 文件可能不完整
|
||||
if er := tw.Close(); er != nil {
|
||||
err = er
|
||||
}
|
||||
}()
|
||||
|
||||
// 获取文件或目录信息
|
||||
fi, er := os.Stat(src)
|
||||
if er != nil {
|
||||
return er
|
||||
}
|
||||
|
||||
// 获取要打包的文件或目录的所在位置和名称
|
||||
srcBase, srcRelative := path.Split(path.Clean(src))
|
||||
|
||||
// 开始打包
|
||||
if fi.IsDir() {
|
||||
tarDir(srcBase, srcRelative, tw, fi)
|
||||
} else {
|
||||
tarFile(srcBase, srcRelative, tw, fi)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 因为要执行遍历操作,所以要单独创建一个函数
|
||||
func tarDir(srcBase, srcRelative string, tw *tar.Writer, fi os.FileInfo) (err error) {
|
||||
// 获取完整路径
|
||||
srcFull := srcBase + srcRelative
|
||||
|
||||
// 在结尾添加 "/"
|
||||
last := len(srcRelative) - 1
|
||||
if srcRelative[last] != os.PathSeparator {
|
||||
srcRelative += string(os.PathSeparator)
|
||||
}
|
||||
|
||||
// 获取 srcFull 下的文件或子目录列表
|
||||
fis, er := ioutil.ReadDir(srcFull)
|
||||
if er != nil {
|
||||
return er
|
||||
}
|
||||
|
||||
// 开始遍历
|
||||
for _, fi := range fis {
|
||||
if fi.IsDir() {
|
||||
tarDir(srcBase, srcRelative+fi.Name(), tw, fi)
|
||||
} else {
|
||||
tarFile(srcBase, srcRelative+fi.Name(), tw, fi)
|
||||
}
|
||||
}
|
||||
|
||||
// 写入目录信息
|
||||
if len(srcRelative) > 0 {
|
||||
hdr, er := tar.FileInfoHeader(fi, "")
|
||||
if er != nil {
|
||||
return er
|
||||
}
|
||||
hdr.Name = srcRelative
|
||||
|
||||
if er = tw.WriteHeader(hdr); er != nil {
|
||||
return er
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 因为要在 defer 中关闭文件,所以要单独创建一个函数
|
||||
func tarFile(srcBase, srcRelative string, tw *tar.Writer, fi os.FileInfo) (err error) {
|
||||
// 获取完整路径
|
||||
srcFull := srcBase + srcRelative
|
||||
|
||||
// 写入文件信息
|
||||
hdr, er := tar.FileInfoHeader(fi, "")
|
||||
if er != nil {
|
||||
return er
|
||||
}
|
||||
hdr.Name = srcRelative
|
||||
|
||||
if er = tw.WriteHeader(hdr); er != nil {
|
||||
return er
|
||||
}
|
||||
|
||||
// 打开要打包的文件,准备读取
|
||||
fr, er := os.Open(srcFull)
|
||||
if er != nil {
|
||||
return er
|
||||
}
|
||||
defer fr.Close()
|
||||
|
||||
// 将文件数据写入 tw 中
|
||||
if _, er = io.Copy(tw, fr); er != nil {
|
||||
return er
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func UnTar(srcTar string, dstDir string) (err error) {
|
||||
// 清理路径字符串
|
||||
dstDir = path.Clean(dstDir) + string(os.PathSeparator)
|
||||
|
||||
// 打开要解包的文件
|
||||
fr, er := os.Open(srcTar)
|
||||
if er != nil {
|
||||
return er
|
||||
}
|
||||
defer fr.Close()
|
||||
|
||||
// 创建 tar.Reader,准备执行解包操作
|
||||
tr := tar.NewReader(fr)
|
||||
|
||||
// 遍历包中的文件
|
||||
for hdr, er := tr.Next(); er != io.EOF; hdr, er = tr.Next() {
|
||||
if er != nil {
|
||||
return er
|
||||
}
|
||||
|
||||
// 获取文件信息
|
||||
fi := hdr.FileInfo()
|
||||
|
||||
// 获取绝对路径
|
||||
dstFullPath := dstDir + hdr.Name
|
||||
|
||||
if hdr.Typeflag == tar.TypeDir {
|
||||
// 创建目录
|
||||
os.MkdirAll(dstFullPath, fi.Mode().Perm())
|
||||
// 设置目录权限
|
||||
os.Chmod(dstFullPath, fi.Mode().Perm())
|
||||
} else {
|
||||
// 创建文件所在的目录
|
||||
os.MkdirAll(path.Dir(dstFullPath), os.ModePerm)
|
||||
// 将 tr 中的数据写入文件中
|
||||
if er := unTarFile(dstFullPath, tr); er != nil {
|
||||
return er
|
||||
}
|
||||
// 设置文件权限
|
||||
os.Chmod(dstFullPath, fi.Mode().Perm())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 因为要在 defer 中关闭文件,所以要单独创建一个函数
|
||||
func unTarFile(dstFile string, tr *tar.Reader) error {
|
||||
// 创建空文件,准备写入解包后的数据
|
||||
fw, er := os.Create(dstFile)
|
||||
if er != nil {
|
||||
return er
|
||||
}
|
||||
defer fw.Close()
|
||||
|
||||
// 写入解包后的数据
|
||||
_, er = io.Copy(fw, tr)
|
||||
if er != nil {
|
||||
return er
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 判断档案是否存在
|
||||
func Exists(name string) bool {
|
||||
_, err := os.Stat(name)
|
||||
return err == nil || os.IsExist(err)
|
||||
}
|
||||
|
||||
// 判断文件是否存在
|
||||
func FileExists(filename string) bool {
|
||||
fi, err := os.Stat(filename)
|
||||
return (err == nil || os.IsExist(err)) && !fi.IsDir()
|
||||
}
|
||||
|
||||
// 判断目录是否存在
|
||||
func DirExists(dirname string) bool {
|
||||
fi, err := os.Stat(dirname)
|
||||
return (err == nil || os.IsExist(err)) && fi.IsDir()
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// zip优缺点
|
||||
|
||||
|
||||
func main() {
|
||||
// 需要压缩的文件路径
|
||||
fileToZip := "test.txt"
|
||||
// 压缩后的文件名
|
||||
zipFileName := "test.zip"
|
||||
|
||||
// 创建一个新的zip文件
|
||||
zipFile, err := os.Create(zipFileName)
|
||||
if err != nil {
|
||||
fmt.Println("创建zip文件失败:", err)
|
||||
return
|
||||
}
|
||||
defer zipFile.Close()
|
||||
|
||||
// 使用zip.Writer将文件写入到zip文件中
|
||||
zipWriter := zip.NewWriter(zipFile)
|
||||
defer zipWriter.Close()
|
||||
|
||||
// 添加文件到zip文件中
|
||||
err = addFileToZip(fileToZip, zipWriter)
|
||||
if err != nil {
|
||||
fmt.Println("添加文件到zip失败:", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("文件压缩成功")
|
||||
}
|
||||
|
||||
func addFileToZip(filePath string, zipWriter *zip.Writer) error {
|
||||
// 打开需要压缩的文件
|
||||
fileToZip, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fileToZip.Close()
|
||||
|
||||
// 获取文件信息
|
||||
fileInfo, err := fileToZip.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 将文件添加到zip文件中
|
||||
fileHeader, err := zip.FileInfoHeader(fileInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fileHeader.Name = filepath.Base(filePath)
|
||||
writer, err := zipWriter.CreateHeader(fileHeader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = io.Copy(writer, fileToZip)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user