使用ioutil包读写文件
读取文件
标准库提供了ioutil包,能够快速执行众多涉及读写文件的操作。
读取一个文件并将其内容打印到终端,程序清单如下:
package main
import (
"fmt"
"io/ioutil"
"log"
)
func main() {
fileBytes, err:=ioutil.ReadFile("main.txt")
if err!=nil{
log.Fatal(err)
}
fileString:=string(fileBytes)
fmt.Println(fileString)
}
如存在的文件,看到被打印出来的文件内容。如不存在的文件,运行结果如下:
2022/01/27 14:05:04 open example.txt: no such file or directory
exit status 1
创建文件
ioutil包提供了用于创建文件的便利函数WriteFile。这个函数设计用于将数据写入文件,但也可使用它来创建文件。函数WriteFile接受一个文件名、要写入文件的数据以及应用于文件的权限。
Go语言使用UNIX权限的数字表示法,很多用于处理文件的函数都将权限值作为参数。
符号表示法 | 数字表示法 | 说明 |
---------- | 0000 | 无权限 |
-rwx------ | 0700 | 只有所有者能够读取、写入和执行 |
-rwxrwx--- | 0770 | 所有者及其所在的用户组能够读取、写入和执行 |
-rwxrwxrwx | 0777 | 所有人能能够读取、写入和执行 |
---x--x--x | 0111 | 所有人都能够执行 |
--w--w--w- | 0222 | 所有人都能够写入 |
--wx-wx-wx | 0333 | 所有人都能够写入和执行 |
-r--r--r-- | 0444 | 所有人都能够读取 |
-r-xr-xr-x | 0555 | 所有人都能够读取和执行 |
-rw-rw-rw- | 0666 | 所有人都能够读取和写入 |
-rwxr----- | -740 | 所有人能够读取、写入和执行,而所有者所在的用户组能够读取 |
在UNIX型系统中,文件的默认权限为0644,即所有者能够读取和写入,而其它人只能读取。
在文件系统中创建了一个文件,并将其权限设置为0644,程序清单如下:
package main
import (
"io/ioutil"
"log"
)
func main() {
b:=make([]byte,0)
err:=ioutil.WriteFile("example.txt",b,0644)
if err!=nil{
log.Fatal(err)
}
}
运行结果:如不存在文件,将创建新的一个空文件example.txt,并给它设置指定的权限。输入ls -l,结果如下:
-rw-r--r-- 1 douxiaobo staff 0 1 27 14:24 example.txt
写入文件
将文件字符串写入文件,程序清单如下:
package main
import (
"io/ioutil"
"log"
)
func main() {
s:="Hello World"
err:=ioutil.WriteFile("example.txt",[]byte(s),0644)
if err!=nil{
log.Fatal(err)
}
}
运行结果:如不存在文件,将会创建新文件,而且有内容“Hello World”。
列出目录的内容
要处理文件系统中的文件,必须知道目录结构。ioutil包提代了便利函数ReadDir,它接受以字符串方式指定的目录名,并返回一个列表,其它包含按文件名排序的文件。文件名的类型为FileInfo,包含如下信息:
Name:文件的名称。
Size:文件的长度,单位为字节。
Mode:用二进制位表示的权限。
ModTime:文件最后一个被修改的时间。
IsDir:文件是否是目录。
Sys:底层数据源。
列出目录中的文件及其权限,程序清单如下:
package main
import (
"fmt"
"io/ioutil"
"log"
)
func main() {
files,err:=ioutil.ReadDir(".")
if err!=nil{
log.Fatal(err)
}
for _,file:=range files{
fmt.Println(file.Mode(),file.Name())
}
}
运行结果如下:
-rw-r--r-- example.txt
-rwxr-xr-x main
-rw-r--r-- main.go
-rw-r--r-- main.txt
-rw-r--r-- main1.txt
-rw-r--r-- temperature.go
-rw-r--r-- temperature_test.go
复制文件
将文件的内容复制到一个新文件中,程序清单如下:
package main
import (
"log"
"os"
"io"
)
func main() {
from, err:=os.Open("./example.txt")
if err!=nil{
log.Fatal(err)
}
defer from.Close()
to,err:=os.OpenFile("./example_cpy.txt",os.O_RDWR|os.O_CREATE,0666)
if err!=nil{
log.Fatal(err)
}
defer to.Close()
_,err=io.Copy(to,from)
if err!=nil{
log.Fatal(err)
}
}
运行结果,成功复制到另一个文件。
删除文件
删除文件,程序清单如下:
package main
import (
"log"
"os"
)
func main() {
err:=os.Remove("./example_cpy.txt")
if err!=nil{
log.Fatal(err)
}
}
运行结果:已经删除example_cpy.txt。
使用文件来管理配置
使用JSON文件存储配置,程序清单如下:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
)
type Config struct{
Name string `json:"name"`
Awake bool `json:"awake"`
Hungry bool `json:"hungry"`
}
func main() {
f,err:=ioutil.ReadFile("config.json")
if err!=nil{
log.Fatal(err)
}
c:=Config{}
err=json.Unmarshal(f,&c)
if err!=nil{
log.Fatal(err)
}
fmt.Printf("%+v\n",c)
}
运行结果:没有json文件,无法试一下运行结果。
使用TOML文件
TOML(Tom's Obvious, Minimal Language)是一种专为存储配置文件而设计的格式。JSON是为序列化数据而设计。
使用TOML文件来存储配置,程序清单如下:
package main
import (
"fmt"
"log"
"github.com/BurntSushi/toml"
)
type Config struct{
Name string
Awake bool
Hungry bool
}
func main() {
c:=Config{}
_,err:=toml.DecodeFile("example.toml",&c)
if err!=nil{
log.Fatal(err)
}
fmt.Printf("%+v\n",c)
}
运行结果如下:(本人不清楚)
{Name: Awake:false Hungry:false}
文件操作:
func Mkdir(name string, perm FileMode) error 创建名称为name的目录,权限设置是perm。
func MkdirAll(path string, perm FileMode) error 根据path创建多级子目录。
func Remove(name string) error 删除名称为name的目录,当目录下有文件或者其它目录时会出错。
func RemoveAll(path string) error根据path删除多级子目录,如果path是单个名称,那么该目录下的子目录全部删除。
代码如下:
package main
import (
"fmt"
"os"
)
func main() {
os.Mkdir("goDir", 0777)
os.MkdirAll("goDir/test1/test2", 0777)
err := os.Remove("goDir")
if err != nil {
fmt.Println(err)
}
os.RemoveAll("goDir")
}
运行结果如下:
remove goDir: The directory is not empty.
创建文件与查看状态:
1、新建文件
1)func Create(name string)(file *File, err Error)
根据提供的文件名创建新的文件,返回一个文件对象,默认权限是0666的文件,返回的文件对象是可读写的。
2)func NewFile(fd uintptr, name string) *File
根据文件描述符创建相应的文件,返回一个文件对象。
2、新建文件夹
func MkdirAll(path string, perm FileMode) error
path表示目录名及子目录,perm表示目录权限,error的值为nil表示创建成功无异常,如果目录已经存在不会执行操作。
3、文件/文件夹状态
func Stat(name string) (FileInfo, error)
如果没有错误将返回描述命名文件的FileInfo。
代码如下:
package main
import (
"fmt"
"log"
"os"
)
var (
newFile *os.File
fileInfo os.FileInfo
err error
path = "test/test2/"
fileName = "demo"
filePath = path + fileName
)
func main() {
//创建文件夹
err = os.MkdirAll(path, 0777)
if err != nil {
fmt.Printf("%s", err)
} else {
fmt.Println("成功创建目录")
}
//创建空白文件
newFile, err = os.Create((filePath))
if err != nil {
log.Fatal(err)
}
fmt.Println(newFile)
newFile.Close()
//查看文件的信息,如果文件不存在,则返回错误
fileInfo, err = os.Stat(filePath)
if err != nil && os.IsNotExist(err) {
log.Fatal("文件不存在。")
} else {
log.Fatal(err)
}
fmt.Println("文件名称:", fileInfo.Name())
fmt.Println("文件大小:", fileInfo.Size())
fmt.Println("文件权限:", fileInfo.Mode())
fmt.Println("最后修改时间:", fileInfo.ModTime())
fmt.Println("是否是文件夹:", fileInfo.IsDir())
fmt.Printf("系统接口类型:%T\n", fileInfo.Sys())
fmt.Printf("系统信息:%+v\n\n", fileInfo.Sys())
}
运行结果如下:(不对)
成功创建目录
&{0xc00007c780}
2022/02/21 16:49:01 <nil>
exit status 1
重命名与移动
func Rename(oldpath, newpath string) error
代码如下:
package main
import (
"log"
"os"
)
func main() {
originalPath := "test.txt"
newPath := "test2.txt"
err := os.Rename(originalPath, newPath)
if err != nil {
log.Fatal(err)
}
}
运行结果如下:(无文件)如有文件,不会出现下面运行结果。
2022/02/21 17:06:05 rename test.txt test2.txt: The system cannot find the file specified.
exit status 1
打开与关闭
代码如下:
package main
import (
"log"
"os"
)
var (
file *os.File
fileInfo os.FileInfo
err error
dirPath = "test/test2/"
fileName = "demo"
filePath = dirPath + fileName
)
func main() {
file, err := os.Open(dirPath)
if err != nil {
log.Fatal(err)
}
buf := make([]byte, 1024)
for {
n, _ := file.Read(buf)
if 0 == n {
break
}
os.Stdout.Write(buf[:n])
}
file.Close()
file, err = os.OpenFile(dirPath, os.O_APPEND, 0666)
if err != nil {
log.Fatal(err)
}
file.Close()
}
运行结果如下:
2022/03/02 20:56:25 open test/test2/: no such file or directory
exit status 1
func Open(name string)(file *File, err Error):该方法打开一个名称为name的文件,但用的是只读方式,内部实现其实是调用了为OpenFile()函数。
func OpenFile(name string, flag int, perm uint32) (file *File, err Error):打开名称为name的文件,flag是打开的方式,包括只读、读写等,perm是权限。
删除与截断
代码如下:
package main
import (
"log"
"os"
)
func main() {
err := os.Remove("test.txt")
if err != nil {
log.Fatal(err)
}
}
运行结果如下:
2022/03/07 14:39:29 remove test.txt: The system cannot find the file specified.
exit status 1
截断函数用于处理文件大小,代码如下:
package main
import (
"log"
"os"
)
func main() {
err := os.Truncate("test.txt", 100)
if err != nil {
log.Fatal(err)
}
}
运行结果如下:
读写文件
1、复制文件
代码如下:
package main
import (
"io"
"log"
"os"
)
var (
newFile *os.File
fileInfo os.FileInfo
err error
path = "test/test2/"
fileName = "demo"
filePath = path + fileName
)
func main() {
//打开原始文件
originalFile, err := os.Open(filePath)
if err != nil {
log.Fatal(err)
}
defer originalFile.Close()
//创建新的文件作为目标文件
newFile, err := os.Create(filePath + "_copy")
if err != nil {
log.Fatal(err)
}
defer newFile.Close()
//从源文件中复制字节到目标文件
bytesWritten, err := io.Copy(newFile, originalFile)
if err != nil {
log.Fatal(err)
}
log.Printf("文件已复制,大小 %d bytes。", bytesWritten)
//将文件内容flush到硬盘中
err = newFile.Sync()
if err != nil {
log.Fatal(err)
}
}
运行结果如下:
2022/03/07 15:01:07 文件已复制,大小 0 bytes。
2、跳转函数
代码如下:
package main
import (
"fmt"
"log"
"os"
)
var (
newFile *os.File
err error
path = "test/test2/"
fileName = "demo"
filePath = path + fileName
)
func main() {
file, _ := os.Open(filePath)
defer file.Close()
//偏离位置,可以是正数也可以是负数
var offset int64 = 5
//用来计算offset的初始位置
//0=文件开始位置
//1=当前位置
//2=文件结尾处
whence := 0
newPosition, err := file.Seek(offset, whence)
if err != nil {
log.Fatal(err)
}
fmt.Println("移动到位置5:", newPosition)
//从当前位置回退两字节
newPosition, err = file.Seek(-2, 1)
if err != nil {
log.Fatal(err)
}
fmt.Println("从当前位置退回两字节:", newPosition)
//使用下面的方式得到当前的位置
currentPosition, err := file.Seek(0, 1)
fmt.Println("当前位置:", currentPosition)
//转到文件开始处
newPosition, err = file.Seek(0, 0)
if err != nil {
log.Fatal(err)
}
fmt.Println("转到文件开始位置(0,0):", newPosition)
}
运行结果如下:
移动到位置5: 5
从当前位置退回两字节: 3
当前位置: 3
转到文件开始位置(0,0): 0
Seek()函数的特点类似于鼠标光标的定位,指定位置之后可以执行复制、剪切、粘贴等操作。
3、写入函数
func (file *File) Write(b []byte) (n int, err Error) 写入byte类型的信息到文件。
func (file *File) WriteAt(b []byte, off int64) (n int, err Error) 在指定位置开始写入byte类型的信息。
func (file *File) WriteString(s string)(ret int, err Error) 写入string信息到文件。
代码如下:
package main
import (
"log"
"os"
)
var (
newFile *os.File
err error
dirPath = "test/test2/"
fileName = "demo"
filePath = dirPath + fileName
)
func main() {
//可写方式打开文件
file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666)
if err != nil {
log.Fatal(err)
}
defer file.Close()
//将字节写入文件中
file.Write([]byte("写入字节。\r\n"))
//将字符串写入文件中
file.WriteString("写入字符串。\r\n")
//打印文件内容
file, err = os.Open(filePath)
if err != nil {
log.Fatal(err)
}
buf := make([]byte, 1024)
for {
n, _ := file.Read(buf)
if 0 == n {
break
}
os.Stdout.Write(buf[:n])
}
file.Close()
}
运行结果如下:(与书上不一样,上下相反)
写入字节。
写入字符串。
权限控制
代码如下:
package main
import (
"log"
"os"
)
var (
file *os.File
err error
dirPath = "test/test2/"
fileName = "demo"
filePath = dirPath + fileName
)
func main() {
//测试写权限
file, err := os.OpenFile(filePath, os.O_WRONLY, 0666)
if err != nil && os.IsPermission(err) {
log.Fatal("错误:没有写入权限。")
} else if os.IsNotExist(err) {
log.Fatal("错误:文件不存在。")
} else {
log.Fatal(err)
}
file.Close()
//测试读权限
file, err = os.OpenFile(filePath, os.O_RDONLY, 0666)
if err != nil && os.IsPermission(err) {
log.Fatal("错误:没有读取权限。")
} else if os.IsNotExist(err) {
log.Fatal("错误:文件不存在。")
} else {
log.Fatal(err)
}
file.Close()
}
运行结果如下:
2022/03/09 14:18:24 <nil>
exit status 1
代码如下:只有Linux下编写代码。
package main
import (
"fmt"
"log"
"os"
"time"
)
var (
file *os.File
fileInfo os.FileInfo
err error
dirPath = "test/test2/"
fileName = "demo"
filePath = dirPath + fileName
)
func main() {
//使用Linux风格改变文件权限
err := os.Chmod(filePath, 0777)
if err != nil {
log.Println(err)
}
//改变文件所有者
err = os.Chown(filePath, os.Getuid(), os.Getgid())
if err != nil {
log.Println(err)
}
//查看文件信息
fileInfo, err = os.Stat(filePath)
if err != nil {
if os.IsNotExist(err) {
log.Fatal("文件不存在。")
}
log.Fatal(err)
}
fmt.Println("最后修改时间:", fileInfo.ModTime())
//改变时间戳
twoDaysFromNow := time.Now().Add(48 * time.Hour)
LastAccessTime := twoDaysFromNow
LastModifyTime := twoDaysFromNow
err = os.Chtimes(filePath, LastAccessTime, LastModifyTime)
if err != nil {
log.Println(err)
}
}
运行结果如下:
2022/03/09 14:29:20 chown test/test2/demo: not supported by windows
最后修改时间: 2022-03-07 15:53:52.9906496 +0800 CST
文件链接
代码如下:
package main
import (
"fmt"
"log"
"os"
)
var (
newFile *os.File
fileInfo os.FileInfo
err error
dirPath = "test/test2/"
fileName = "demo"
filePath = dirPath + fileName
)
func main() {
//创建一个硬链接
//创建后同一个文件内容会有两个文件名,改变一个文件的内容会影响另一个
//删除和重命名不会影响另一个
hardLink := filePath + "h1"
err := os.Link(filePath, hardLink)
if err != nil {
log.Println(err)
}
fmt.Println("创建硬链接")
//创建一个软链接
softLink := filePath + "s1"
err = os.Symlink(fileName, softLink)
if err != nil {
log.Println(err)
}
fmt.Println("创建软链接")
/*Lstat返回一个文件的信息,但是当文件是一个较链接时,它返回软链接的信息,而不是引用的文件的信息*/
//Symlink在Windows中不工作
fileInfo, err := os.Lstat(softLink)
if err != nil {
log.Fatal(err)
}
fmt.Printf("链接信息:%+v", fileInfo)
//改变软链接的拥有得不会影响原始文件
err = os.Lchown(softLink, os.Getuid(), os.Getgid())
if err != nil {
log.Fatal(err)
}
}
运行结果如下:
创建硬链接
2022/03/09 14:58:07 symlink demo test/test2/demos1: A required privilege is not held by the client.
创建软链接
2022/03/09 14:58:07 CreateFile test/test2/demos1: The system cannot find the file specified.
exit status 1
XML处理
1、解析XML
func Unmarshal(data []byte, v interface{} error
data接收的是XML数据流,v是需要输出的结构,定义为interface,也就是可以把XML转换为任意格式。
代码如下:
package main
import (
"encoding/xml"
"fmt"
"io/ioutil"
"os"
)
type Recurlyservers struct {
XMLName xml.Name `xml:"servers"`
Version string `xml:"version,attr"`
Svs []server `xml:"server"`
Description string `xml:",innerxml"`
}
type server struct {
XMLName xml.Name `xml:"server"`
ServerName string `xml:"serverName"`
ServerIP string `xml:"serverIP"`
}
func main() {
file, err := os.Open("servers.xml")
if err != nil {
fmt.Print("error: %v", err)
return
}
defer file.Close()
data, err := ioutil.ReadAll(file)
if err != nil {
fmt.Printf("error: %v", err)
return
}
v := Recurlyservers{}
err = xml.Unmarshal(data, &v)
if err != nil {
fmt.Printf("error: %v", err)
return
}
fmt.Println(v)
}
运行结果如下:
error: %vopen servers.xml: The system cannot find the file specified.
2、生成XML
func Marshal(v interface{}) ([]byte,error)
func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
代码如下:
package main
import (
"encoding/xml"
"fmt"
"os"
)
type Servers struct {
XMLName xml.Name `xml:"servers"`
Version string `xml:"version,attr"`
Svs []server `xml:"server"`
}
type server struct {
ServerName string `xml:"serverName"`
ServerIP string `xml:"serverIP"`
}
func main() {
v := &Servers{Version: "1"}
v.Svs = append(v.Svs, server{"Local_Web", "172.0.0.1"})
v.Svs = append(v.Svs, server{"Local_DB", "172.0.0.2"})
output, err := xml.MarshalIndent(v, " ", " ")
if err != nil {
fmt.Printf("error: %v\n", err)
}
os.Stdout.Write([]byte(xml.Header))
os.Stdout.Write(output)
}
运行结果如下:
<?xml version="1.0" encoding="UTF-8"?>
<servers version="1">
<server>
<serverName>Local_Web</serverName>
<serverIP>172.0.0.1</serverIP>
</server>
<server>
<serverName>Local_DB</serverName>
<serverIP>172.0.0.2</serverIP>
</server>
</servers>
JSON处理
1、解析JSON
一种是解析到结构体,另一种是解析到接口。
func Unmarshal(data []byte, v interface{}) error
代码如下:
package main
import (
"encoding/json"
"fmt"
)
type Server struct {
ServerName string
ServerIP string
}
type Serverslice struct {
Servers []Server
}
func main() {
var s Serverslice
str := `{"servers":[{"serverName":"Local_Web","serverIP":"172.0.0.1"},{"serverName":"Local_DB","serverIP":"172.0.0.2"}]}`
json.Unmarshal([]byte(str), &s)
fmt.Println(s)
}
运行结果如下:
{[{Local_Web 172.0.0.1} {Local_DB 172.0.0.2}]}
2、生成JSON
func Marshal(v interface{}) ([]byte, error)
代码如下:
package main
import (
"encoding/json"
"fmt"
)
type Server struct {
ServerName string
ServerIP string
}
type Serverslice struct {
Servers []Server
}
func main() {
var s Serverslice
s.Servers = append(s.Servers, Server{ServerName: "Local_Web", ServerIP: "172.0.0.1"})
s.Servers = append(s.Servers, Server{ServerName: "Local_DB", ServerIP: "172.0.0.2"})
b, err := json.Marshal(s)
if err != nil {
fmt.Println("json err:", err)
}
fmt.Println(string(b))
}
运行结果如下:
{"Servers":[{"ServerName":"Local_Web","ServerIP":"172.0.0.1"},{"ServerName":"Local_DB","ServerIP":"172.0.0.2"}]}
日志记录
1、Logrus
安装logrus的命令行如下:
go get -u github.com/sirupsen/logrus
运行结果如下:
package golang.org/x/sys/unix: unrecognized import path "golang.org/x/sys/unix": https fetch: Get "https://golang.org/x/sys/unix?go-get=1": dial tcp 142.251.42.241:443: i/o timeout
代码如下:
package main
import (
log "github.com/Sirupsen/logrus"
)
func main() {
log.WithFields(log.Fields{
"tool": "pen",
}).Info("This is pen.")
}
运行结果如下:
../github.com/Sirupsen/logrus/terminal_check_bsd.go:6:8: cannot find package "golang.org/x/sys/unix" in any of:
/usr/local/go/src/golang.org/x/sys/unix (from $GOROOT)
/Users/douxiaobo/go/src/golang.org/x/sys/unix (from $GOPATH)
代码如下:
package main
import (
"os"
log "github.com/Sirupsen/logrus"
)
func init() {
//日志格式化为JSON而不是默认的ASCII
log.SetFormatter(&log.JSONFormatter{})
//输出stdout而不是默认的stderr,也可以是一个文件
log.SetOutput(os.Stdout)
//只记录严重或以上警告
log.SetLevel(log.WarnLevel)
}
func main() {
log.WithFields(log.Fields{
"tool": "pen",
"price": 10,
}).Info("The pen price is 10 dollars.")
contextLogger := log.WithFields(log.Fields{
"common": "这是一个字段",
"other": "其他你想记录的东西",
})
contextLogger.Info("此处会记录common和other字段")
}
运行结果如下:
../github.com/Sirupsen/logrus/terminal_check_bsd.go:6:8: cannot find package "golang.org/x/sys/unix" in any of:
/usr/local/go/src/golang.org/x/sys/unix (from $GOROOT)
/Users/douxiaobo/go/src/golang.org/x/sys/unix (from $GOPATH)
2、Seelog
安装Seelog的命令行如下:
go get -u github.com/cihub/seelog
运行结果如下:
# cd .; git clone -- https://github.com/cihub/seelog /Users/douxiaobo/go/src/github.com/cihub/seelog
Cloning into '/Users/douxiaobo/go/src/github.com/cihub/seelog'...
fatal: unable to access 'https://github.com/cihub/seelog/': LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to github.com:443
package github.com/cihub/seelog: exit status 128
代码如下:
package main
import (
log "github.com/cihub/seelog"
)
func main() {
defer log.Flush()
log.Info("你好,Seelog。")
}
运行结果如下:
tempCodeRunnerFile.go:4:2: cannot find package "github.com/cihub/seelog" in any of:
/usr/local/go/src/github.com/cihub/seelog (from $GOROOT)
/Users/douxiaobo/go/src/github.com/cihub/seelog (from $GOPATH)
运行结果如下:
main.go:4:2: cannot find package "github.com/cihub/seelog" in any of:
/usr/local/go/src/github.com/cihub/seelog (from $GOROOT)
/Users/douxiaobo/go/src/github.com/cihub/seelog (from $GOPATH)
压缩
1、打包与解包
代码如下:
package main
import (
"archive/zip"
"log"
"os"
)
func main() {
//创建一个打包文件
outFile, err := os.Create("test.zip")
if err != nil {
log.Fatal(err)
}
defer outFile.Close()
//使用zip包的创建函数zipWriter用于写入文件
zipWriter := zip.NewWriter(outFile)
//往打包文件中写文件
var filesToArchive = []struct {
name, Body string
}{
{"test.txt", "String contents of file"},
{"test2.txt", "\x61\x62\x63\n"},
}
//下面将要打包的内容写入打包文件中,依次写入
for _, file := range filesToArchive {
fileWriter, err := zipWriter.Create(file.name)
if err != nil {
log.Fatal(err)
}
_, err = fileWriter.Write([]byte(file.Body))
if err != nil {
log.Fatal(err)
}
}
//清理
err = zipWriter.Close()
if err != nil {
log.Fatal(err)
}
}
运行结果如下:
代码如下:
package main
import (
"archive/zip"
"io"
"log"
"os"
"path/filepath"
)
func main() {
zipReader, err := zip.OpenReader("test.zip")
if err != nil {
log.Fatal(err)
}
defer zipReader.Close()
//遍历打包文件中的每一文件/文件夹
for _, file := range zipReader.Reader.File {
zippedFile, err := file.Open()
if err != nil {
log.Fatal()
}
defer zippedFile.Close()
//指定提取的文件名
//你可以指定全路径名或者一个前缀,这样可以把它们放在不同的文件夹中
//这个例子使用打包文件中相同的文件名
targetDir := "./"
extractedFilePath := filepath.Join(
targetDir,
file.Name,
)
if file.FileInfo().IsDir() {
//创建文件夹并设置同样的权限
log.Println("正在创建目录:", extractedFilePath)
os.MkdirAll(extractedFilePath, file.Mode())
} else {
//提取正常的文件
log.Println("正在提取文件:", file.Name)
outputFile, err := os.OpenFile(
extractedFilePath,
os.O_WRONLY|os.O_CREATE|os.O_TRUNC,
file.Mode(),
)
if err != nil {
log.Fatal(err)
}
defer outputFile.Close()
//通过io.Copy简洁地复制文件内容
_, err = io.Copy(outputFile, zippedFile)
if err != nil {
log.Fatal(err)
}
}
}
}
运行结果如下:
2022/03/14 10:53:24 正在提取文件: test.txt
2022/03/14 10:53:24 正在提取文件: test2.txt
2、压缩与解压
代码如下:
package main
import (
"compress/gzip"
"log"
"os"
)
func main() {
outputFile, err := os.Create("test.txt.gz")
if err != nil {
log.Fatal(err)
}
gzipWriter := gzip.NewWriter(outputFile)
defer gzipWriter.Close()
_, err = gzipWriter.Write([]byte("Gophers rule!\n"))
if err != nil {
log.Fatal(err)
}
log.Println("已经压缩数据并写入文件。")
}
运行结果如下:
2022/03/14 17:01:05 已经压缩数据并写入文件。
代码如下:
package main
import (
"compress/gzip"
"io"
"log"
"os"
)
func main() {
//打开一个gzip文件
gzipFile, err := os.Open("test.txt.gz")
if err != nil {
log.Fatal(err)
}
gzipReader, err := gzip.NewReader(gzipFile)
if err != nil {
log.Fatal(err)
}
defer gzipReader.Close()
//解压缩到一个writer,它是一个file writer
outfileWriter, err := os.Create("unzipped.txt")
if err != nil {
log.Fatal(err)
}
defer outfileWriter.Close()
//复制内容
_, err = io.Copy(outfileWriter, gzipReader)
if err != nil {
log.Fatal()
}
}
运行结果如下: