commit d4fe76566ee473fa803658a14088667384b8c874 Author: Yun Date: Sun May 3 22:35:47 2026 +0800 commit diff --git a/tar.gzx.go b/tar.gzx.go new file mode 100644 index 0000000..cc80a87 --- /dev/null +++ b/tar.gzx.go @@ -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 + // ... +} diff --git a/tarx.go b/tarx.go new file mode 100644 index 0000000..339ebdf --- /dev/null +++ b/tarx.go @@ -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() +} \ No newline at end of file diff --git a/zipx.go b/zipx.go new file mode 100644 index 0000000..1ae4b4c --- /dev/null +++ b/zipx.go @@ -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 +}