Go 标准库之 os 文件操作

https://pkg.go.dev/os

1、介绍

Go语言中,文件操作的大多数函数都在os包里面,文件的信息包括文件名、文件大小、修改权限、修改时间等。

1.1、文件接口属性(FileInfo)

1
2
3
4
5
6
7
8
type FileInfo interface {
Name() string // 文件名
Size() int64 // 文件大小
Mode() FileMode // 修改权限
ModTime() time.Time // 最后修改时间
IsDir() bool // 判断是否是目录
Sys() interface{} // 文件的详细信息,获取的值是*syscall.Stat_t类型
}

FileMode代表文件的模式和权限位。这些字位在所有的操作系统都有相同的含义,因此文件的信息可以在不同的操作系统之间安全的移植。不是所有的位都能用于所有的系统,唯一共有的是用于表示目录的ModeDir位。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const (
// 单字符是被String方法用于格式化的属性缩写。
ModeDir FileMode = 1 << (32 - 1 - iota) // d: 目录
ModeAppend // a: 只能写入,且只能写入到末尾
ModeExclusive // l: 用于执行
ModeTemporary // T: 临时文件(非备份文件)
ModeSymlink // L: 符号链接(不是快捷方式文件)
ModeDevice // D: 设备
ModeNamedPipe // p: 命名管道(FIFO)
ModeSocket // S: Unix域socket
ModeSetuid // u: 表示文件具有其创建者用户id权限
ModeSetgid // g: 表示文件具有其创建者组id的权限
ModeCharDevice // c: 字符设备,需已设置ModeDevice
ModeSticky // t: 只有root/创建者能删除/移动文件
// 覆盖所有类型位(用于通过&获取类型位),对普通文件,所有这些位都不应被设置
ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice
ModePerm FileMode = 0777 // 覆盖所有Unix权限位(用于通过&获取类型位)
)

这些被定义的位是FileMode最重要的位。另外9个不重要的位为标准Unix rwxrwxrwx权限(任何人都可读、写、运行)。这些(重要)位的值应被视为公共API的一部分,可能会用于线路协议或硬盘标识:它们不能被修改,但可以添加新的位。

1.2、文件信息结构体(fileStat)

1
2
3
4
5
6
7
type fileStat struct {
name string
size int64
mode FileMode
modTime time.Time
sys syscall.Stat_t
}

1、fileStat 结构体的常用方法汇总

方法名 描述
Name() string 返回文件名
IsDir() bool 判断是否是目录
Size() int64 返回文件大小
Mode() FileMode 返回文件权限
ModTime() time.Time 文件的最后修改时间
Sys() interface{} 文件的详细信息,获取的值是*syscall.Stat_t类型

2、使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import (
"fmt"
"os"
)

func main(){
fp := "./public/test1.txt"
fileInfo, err := os.Stat(fp)
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Printf("类型: %T\n",fileInfo)
fmt.Printf("文件名: %v\n",fileInfo.Name())
fmt.Printf("文件大小: %v\n",fileInfo.Size())
fmt.Printf("是否为目录: %v\n",fileInfo.IsDir())
fmt.Printf("文件权限: %v\n",fileInfo.Mode())
fmt.Printf("文件最后修改的时间: %v\n",fileInfo.ModTime())
}
/**输出
类型: *os.fileStat
文件名: test1.txt
文件大小: 11
是否为目录: false
文件权限: -rw-r--r--
文件最后修改的时间: 2021-01-15 16:29:53.816034553 +0800 CST
sys: &{Dev:16777220 Mode:33188 Nlink:1 Ino:15440327 Uid:501 Gid:20 Rdev:0 Pad_cgo_0:[0 0 0 0] Atimespec:{Sec:1610699394 Nsec:591237565} Mtimespec:{Sec:1610699393 Nsec:816034553} Ctimespec:{Sec:1610699393 Nsec:816034553} Birthtimespec:{Sec:1610611801 Nsec:544367649} Size:11 Blocks:8 Blksize:4096 Flags:0 Gen:0 Lspare:0 Qspare:[0 0]}
*/

2、目录操作

2.1、方法列表

method 描述
os.Mkdir(name string, perm FileMode) error 创建名称为name的目录,权限设置是perm
os.MkdirAll(path string, perm FileMode) error 根据path创建多级子目录
os.Remove(name string) error 删除名称为name的目录,当目录下有文件或者其他目录会出错,该函数也可用于删除目录(只能删除空目录)。如果要删除非空目录,需要使用 RemoveAll() 函数
os.RemoveAll(path string) error 根据path删除多级子目录
os.Getwd() (dir string, err error) 获得工作目录
os.(f *File) Chdir() error 改变工作目录到f,其中f必须为一个目录,否则便会报错
os.(f *File) Chdir() error 改变工作目录到f,其中f必须为一个目录,否则便会报错
os.TempDir() string 获得临时目录

2.2、使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package main
import (
"fmt"
"os"
)
func main(){
dirName := "./img"
// 创建目录,并分配权限
err := os.Mkdir(dirName, os.ModePerm)
if err != nil {
fmt.Println(err.Error())
}
fmt.Println( dirName+ " 创建成功!")
// 创建多级目录
dirName2 := "./public/static/css"
err = os.MkdirAll(dirName2,os.ModePerm)
if err != nil {
fmt.Println(err.Error())
}
fmt.Println( dirName2+ " 创建成功!")

// 删除目录
err := os.Remove("./file")
if err != nil {
fmt.Println("Remove-> 删除失败: " + err.Error())
} else {
fmt.Println("Remove-> 删除成功!" )
}
// 删除多级子目录
err2 := os.RemoveAll("./file/static")
if err2 != nil {
fmt.Println("RemoveAll-> 删除失败: " + err2.Error())
} else {
fmt.Println("RemoveAll-> 删除成功!" )
}
}


// 判断文件或者目录是否存在
func pathIsExist(pathName string) (bool,error) {
// 获取文件或目录信息
_, err := os.Stat(pathName)
// 如果文件或目录存在,则err== nil
if err == nil {
return true, nil
}
// 使用os.IsNotExist()判断返回的错误类型是否为true,true:说明文件或文件夹不存在
if os.IsNotExist(err) {
return false,nil
}
// 如果错误类型为其它,则不确定是否在存在
return false,err
}

3、文件操作

3.1、方法列表

方法名 描述
os.Create(name string) (file *File, err error) 创建文件,如果文件存在,会将其覆盖,本质上调用的是OpenFile
os.Open(name string) (*File, error) 只读模式打开文件,本质上调用的是OpenFile
os.OpenFile(name string, flag int, perm FileMode) (*File, error) 打开文件。参数1:要打开的文件路径;参数2:文件打开模式,如 O_RDONLYO_WRONGLYO_RDWR,还可以通过管道符来指定文件不存在时创建文件;数3:文件创建时候的权限级别,在0-7之间,常用参数为6
os.Rename(oldpath, newpath string) error 重命名文件
os.Chmod(name string, mode FileMode) error 修改文件权限
os.Chown(name string, uid, gid int) error 修改文件所有者
os.Stat(name string) (FileInfo, error) 获取文件描述信息

OpenFile 入参 flag 介绍

1
2
3
4
5
6
7
8
9
10
const (
O_RDONLY int = syscall.O_RDONLY // 只读模式打开文件
O_WRONLY int = syscall.O_WRONLY // 只写模式打开文件
O_RDWR int = syscall.O_RDWR // 读写模式打开文件
O_APPEND int = syscall.O_APPEND // 写操作时将数据附加到文件尾部
O_CREATE int = syscall.O_CREAT // 如果不存在将创建一个新文件
O_EXCL int = syscall.O_EXCL // 和O_CREATE配合使用,文件必须不存在
O_SYNC int = syscall.O_SYNC // 打开文件用于同步I/O
O_TRUNC int = syscall.O_TRUNC // 如果可能,打开时清空文件
)

3.2、使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package main
import (
"fmt"
"os"
)
func main(){
fileName := "./file/a.txt"
//创建文件
// 如果文件存在,则会覆盖
create, err := os.Create(fileName)
if err != nil {
fmt.Println("创建失败: " + err.Error())
return
}
fmt.Printf("创建成功! %v\n",create)


// 打开文件
// 该文件不存在
fileName := "./public/test.txt"
file1, err := os.Open(fileName)
if err != nil {
fmt.Printf("os.Open 打开文件失败,err:%s \n" , err.Error()) //打开文件失败,err:open ./public/test.txt: no such file or directory
} else {
fmt.Printf("os.Open 打开文件成功,open:%v \n" , file1)
// 关闭文件
defer file1.Close()
}
// 文件不存在,则会创建文件
file2, err1 := os.OpenFile(fileName,os.O_CREATE,os.ModePerm)
if err1 != nil {
fmt.Printf("os.OpenFile 打开文件失败,err:%s \n" , err1.Error())
} else {
fmt.Printf("os.OpenFile 打开文件成功,open:%v \n" , file2) // os.OpenFile 打开文件成功,open:&{0xc0000b0120}
// 关闭文件
defer file2.Close()
}


// 读取文件
// 定义一个变量存储读取的内容
b := make([]byte,1024)
// 读取文件
for {
read, _ := file1.Read(b)
if read == 0 {
break
}
}
fmt.Printf("读取内容: %s \n",b) // 读取内容: Hello Word! 您好,世界!
// 关闭文件
_ = file1.Close()


// 写入文件
fileName := "./public/hello.txt"
// 读写|创建|追加的模式 模式打开文件
file1, err := os.OpenFile(fileName,os.O_RDWR | os.O_CREATE | os.O_APPEND ,os.ModePerm )
if err != nil {
fmt.Printf("os.OpenFile 打开文件失败,err:%s \n" , err.Error())
return
}
// 写入文件
write, err := file1.Write([]byte("Go! Go! Let's Go!! 汉字 \n"))
if err != nil {
fmt.Printf("写入失败: %s \n",err.Error())
}
fmt.Printf("写入字节数: %d \n",write)
// 关闭文件
_ = file1.Close()
}

Go 标准库之 os 文件操作
https://flepeng.github.io/021-Go-32-Go-标准库-Go-标准库之-os-文件操作/
作者
Lepeng
发布于
2024年12月3日
许可协议