package main
import (
"archive/tar"
"bytes"
"io"
"fmt"
"io/ioutil"
"log"
"reflect"
"os"
"time"
)
// 文件类型
const (
TypeReg = tar.TypeReg // 普通文件
TypeLink = tar.TypeLink // 硬链接
TypeSymlink = tar.TypeSymlink // 符号链接
TypeChar = tar.TypeChar // 字符节点
TypeBlock = tar.TypeBlock // 块节点
TypeDir = tar.TypeDir // 目录
TypeFifo = tar.TypeFifo // 先进先出队列节点
TypeCont = tar.TypeCont // 保留位
TypeXHeader = tar.TypeXHeader // 扩展头
TypeXGlobalHeader = tar.TypeXGlobalHeader // 全局扩展头
TypeGNULongName = tar.TypeGNULongName // 下一个文件记录有个长名字
TypeGNULongLink = tar.TypeGNULongLink // 下一个文件记录指向一个具有长名字的文件
TypeGNUSparse = tar.TypeGNUSparse // 稀疏文件
)
// 实现了tar格式压缩文件的存取
func main() {
// 被打包的包名
tarFilePathName := "test.tar"
// 需要打包的文件 或者目录
//tarFileReadName := "网页操作"
tarFileReadName := "a.txt"
// tar打包
tarCompresss(tarFilePathName,tarFileReadName)
}
// tar 打包
func tarCompresss(tarFilePathName string,tarFileReadName string) {
// 实例化一个结构体切片
var files []struct{ Name string; Body string }
//files := []struct {Name string;Body string}{}
// 定义一个结构体用于存放文本文件信息
type filess struct {Name,Body string}
//声明buffer
var buf bytes.Buffer
// 初始化writer
var tw = tar.NewWriter(&buf)
// 判断被打包的文件是文件夹还是文本文件
fi, e := os.Stat(tarFileReadName)
if e != nil {
fmt.Println("文件不存在")
}
if fi.IsDir() {
fmt.Println("是目录")
// 循环遍历目录中所有的文件
files = listFiles(tarFileReadName)
} else {
fmt.Println("是文本文件")
files = listFile(tarFileReadName)
}
for _, file := range files {
// 打开文件并获取信息
f, err := os.Open(file.Name)
if err != nil {
fmt.Println(err)
}
// 获取文件信息
fii,_ := os.Stat(file.Name)
// 根据结构体的内容实例化一个header
hdr := &tar.Header{
Name: file.Name, // 记录头域的文件名
Mode: 0666, // 权限和模式位
Uid: 0, // 所有者的用户ID
Gid: 0, // 所有者的组ID
Size: fii.Size(), // 字节数(长度)
ModTime: time.Now(), // 修改时间
Typeflag: TypeReg, // 文件类型
Linkname: "", // 链接的目标名
Uname: "", // 所有者的用户名
Gname: "", // 所有者的组名
Devmajor: 0, // 字符设备或块设备的major number
Devminor: 0, // 字符设备或块设备的minor number
AccessTime: time.Now(), // 访问时间
ChangeTime: time.Now(), // 状态改变时间
}
// writer写入header
if err := tw.WriteHeader(hdr); err != nil {
log.Fatal(err)
}
var buff [2048]byte
for {
n, err := f.Read(buff[:])
tw.Write(buff[:n])
fmt.Println(reflect.TypeOf(buff[:n]))
if err != nil {
if err == io.EOF {
break
}
fmt.Println(err)
}
}
}
// 关闭writer
if err := tw.Close(); err != nil {
log.Fatal(err)
}
// 自动生成并写入文件
if err := ioutil.WriteFile(tarFilePathName, buf.Bytes(), os.ModePerm); err != nil {
log.Fatal(err)
}
}
// 循环遍历目录中所有的文件
func listFiles(dirName string) []struct{ Name string; Body string } {
// 实例化一个结构体切片
var files = []struct {
Name, Body string
}{ }
type filess struct {
Name,Body string
}
var listDirFiles func(dirName string)
listDirFiles = func(dirName string) {
fileInfos, err := ioutil.ReadDir(dirName)
if err != nil {
log.Fatal(err)
}
for _, fi := range fileInfos {
filename := dirName + "/" + fi.Name()
if fi.IsDir() {
//递归调用方法
listDirFiles(filename)
} else {
//fmt.Printf("%s\n", filename)
//fmt.Println(reflect.TypeOf(filename))
files = append(files,filess{filename,""})
}
}
}
listDirFiles(dirName)
fmt.Println(reflect.TypeOf(files))
return files
}
// 单个文件处理
func listFile(onlyFileName string) []struct{ Name string; Body string } {
//var order []string
// 实例化一个结构体切片
var files = []struct {
Name, Body string
}{ }
type filess struct {
Name,Body string
}
var fileName func(onlyFileName string)
fileName = func(onlyFileName string) {
files = append(files,filess{onlyFileName,""})
}
fileName(onlyFileName)
fmt.Println(reflect.TypeOf(files))
return files
}