🌙 1.os操作文件
🌙 1.创建文件
- 打开文件
os.Create
func testCreate() {
f, err := os.Create("./test.txt")
defer func(f *os.File) {
err := f.Close()
if err != nil {
fmt.Println("文件关闭失败", err)
}
}(f)
if err != nil {
fmt.Println("文件创建失败", err)
return
}
fmt.Println("文件创建成功", f)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
使用Create()创建文件时:
- 如果文件不存在,则创建文件。
- 如果文件存在,则清空文件内内容。
- Create创建的文件,未添加权限,任何人都可以读写。
🌙 2.打开文件
- 打开文件
os.OpenFile
func testOpen() {
f, err := os.OpenFile("test.txt", os.O_APPEND | os.O_RDWR, os.ModeAppend)
defer func(f *os.File) {
err := f.Close()
if err != nil {
fmt.Println("文件关闭失败", err)
}
}(f)
if err != nil {
fmt.Println("open file err: ", err)
return
}
fmt.Println("文件打开成功", f)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
常用的文件打开模式:
// Flags to OpenFile wrapping those of the underlying system. Not all
// flags may be implemented on a given system.
const (
// Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified.
O_RDONLY int = syscall.O_RDONLY // open the file read-only.只读
O_WRONLY int = syscall.O_WRONLY // open the file write-only.只写
O_RDWR int = syscall.O_RDWR // open the file read-write.读写
// The remaining values may be or'ed in to control behavior.
O_APPEND int = syscall.O_APPEND // append data to the file when writing.追加
O_CREATE int = syscall.O_CREAT // create a new file if none exists.创建
O_EXCL int = syscall.O_EXCL // used with O_CREATE, file must not exist.
O_SYNC int = syscall.O_SYNC // open for synchronous I/O.同步IO
O_TRUNC int = syscall.O_TRUNC // truncate regular writable file when opened.清空
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
🌙 3.文件写入
- 写入字节
Write()
func testWrite() {
f, err := os.OpenFile("test.txt", os.O_CREATE | os.O_WRONLY, os.ModePerm)
defer func(f *os.File) {
err := f.Close()
if err != nil {
fmt.Println("文件关闭失败", err)
}
}(f)
if err != nil {
fmt.Println("open file err: ", err)
return
}
fmt.Println("文件打开成功", f)
var num int
num, err = f.Write([]byte("Hello world!"))
if err != nil {
fmt.Println("write file err: ", err)
return
}
fmt.Println("write num = ", num) // 每次都会从头开始重新写入
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
如果我们不想每次写入都会从头开始重新写入,那么需要将打开模式修改为:os.O_CREATE | os.O_WRONLY | os.O_APPEND
- 按字符串写
WriteString()
:
// 写入文件内容
n, err := f.WriteString(["hello"])// 会将前5个字符替换为 hello
if err != nil {
fmt.Println("write err: ", err)
return
}
fmt.Println("write number = ", n)
1
2
3
4
5
6
7
2
3
4
5
6
7
🌙 4.修改读写位置
修改文件的读写指针位置 Seek()
,包含两个参数:
- 参数1:偏移量,为正数时向文件尾偏移,为负数时向文件头偏移
- 参数2:偏移的开始位置,包括:
io.SeekStart
:从文件起始位置开始io.SeekCurrent
:从文件当前位置开始io.SeekEnd
:从文件末尾位置开始
Seek()
函数返回
f, _ := os.OpenFile("test.txt",os.O_RDWR, 6)
off, _ := f.Seek(5, io.SeekStart)
fmt.Println(off) // 5
n, _ := f.WriteAt([]byte("hahahh"), off)
fmt.Println(n)
f.Close()
1
2
3
4
5
6
2
3
4
5
6
🌙 5.读取文件
- 按字节读取:
f.Read
func testRead() {
readByte := make([]byte, 128)
f, err := os.OpenFile("test.txt", os.O_RDONLY, os.ModeAppend)
defer func(f *os.File) {
err := f.Close()
if err != nil {
fmt.Println("文件关闭失败", err)
}
}(f)
if err != nil {
fmt.Println("open file err: ", err)
return
}
fmt.Println("文件打开成功", f)
for {
n, err := f.Read(readByte)
if err != nil && err != io.EOF{
fmt.Println("read file : ", err)
break
}
fmt.Println("read: ", string(readByte[:n]))
if n < 128 {
fmt.Println("read end")
break
}
}
}
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
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
🌙 5.删除文件
- 删除文件
os.Remove
func testRemove() {
err := os.Remove("test.txt")
if err != nil {
fmt.Println("remove file err", err)
return
}
fmt.Println("remove file success")
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
该函数也可用于删除目录(只能删除空目录)。如果要删除非空目录,需要使用 RemoveAll()
函数
🌙 6.目录操作
- 判断对路径:
filepath.IsAbs
- 转为绝对路径:
filepath.Abs
- 创建目录:
os.Mkdir
、os.MkdirAll
// 路径操作
fmt.Println(filepath.IsAbs("./test.txt")) // false:判断是否是绝对路径
fmt.Println(filepath.Abs("./test.txt")) // 转换为绝对路径
// 创建目录
err := os.Mkdir("./test", os.ModePerm)
if err != nil {
fmt.Println("mkdir err: ", err)
return
}
// 创建多级目录
err = os.MkdirAll("./dd/rr", os.ModePerm)
if err != nil {
fmt.Println("mkdirAll err: ", err)
return
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ps:Openfile()
可以用于打开目录。
🌙 2.bufio操作文件
bufio
封装了io.Reader
、io.Writer
接口对象,并创建了另一个也实现了该接口的对象:bufio.Reader
、bufio.Writer
。
通过该实现,bufio
实现了文件的缓冲区设计,可以大大提高文件I/O的效率。
使用bufio
读取文件时,先将数据读入内存的缓冲区(缓冲区一般比要比程序中设置的文件接收对象要大),这样就可以有效降低直接I/O的次数。
bufio.Read([]byte)
相当于读取大小len(p)
的内容:
- 当缓冲区有内容时,将缓冲区内容全部填入p并清空缓冲区
- 当缓冲区没有内容且
len(p)>len(buf)
,即要读取的内容比缓冲区还要大,直接去文件读取即可 - 当缓冲区没有内容且
len(p)<len(buf)
,即要读取的内容比缓冲区小,读取文件内容并填满缓冲区,并将p填满 - 以后再次读取时,缓冲区有内容,将缓冲区内容全部填入p并清空缓冲区(和第一步一致)
func testBufioWrite() {
f, err := os.Create("./test.txt")
defer func(f *os.File) {
err := f.Close()
if err != nil {
fmt.Println("文件关闭失败", err)
}
}(f)
if err != nil {
fmt.Println("文件创建失败", err)
return
}
fmt.Println("文件创建成功", f)
writer := bufio.NewWriter(f)
_, err = writer.WriteString("hello world!")
if err != nil {
fmt.Println("write err:", err)
return
}
err = writer.Flush()
if err != nil {
return
}
}
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
🌙 3.ioutil操作文件
ioutil.ReadFile
读取文件ioutil.WriteFile
写入文件
func testIoutil() {
ret, err := ioutil.ReadFile("test.txt")
if err != nil {
fmt.Println("read err :", err)
return
}
fmt.Println(string(ret))
s := "你好世界"
err = ioutil.WriteFile("test.txt", []byte(s), os.ModePerm)
if err != nil {
fmt.Println("WriteFile err", err)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
ioutil
读写文件源码实现:
// ReadAll reads from r until an error or EOF and returns the data it read.
// A successful call returns err == nil, not err == EOF. Because ReadAll is
// defined to read from src until EOF, it does not treat an EOF from Read
// as an error to be reported.
//
// As of Go 1.16, this function simply calls io.ReadAll.
func ReadAll(r io.Reader) ([]byte, error) {
return io.ReadAll(r)
}
// ReadFile reads the file named by filename and returns the contents.
// A successful call returns err == nil, not err == EOF. Because ReadFile
// reads the whole file, it does not treat an EOF from Read as an error
// to be reported.
//
// As of Go 1.16, this function simply calls os.ReadFile.
func ReadFile(filename string) ([]byte, error) {
return os.ReadFile(filename)
}
// WriteFile writes data to a file named by filename.
// If the file does not exist, WriteFile creates it with permissions perm
// (before umask); otherwise WriteFile truncates it before writing, without changing permissions.
//
// As of Go 1.16, this function simply calls os.WriteFile.
func WriteFile(filename string, data []byte, perm fs.FileMode) error {
return os.WriteFile(filename, data, perm)
}
// ReadDir reads the directory named by dirname and returns
// a list of fs.FileInfo for the directory's contents,
// sorted by filename. If an error occurs reading the directory,
// ReadDir returns no directory entries along with the error.
//
// As of Go 1.16, os.ReadDir is a more efficient and correct choice:
// it returns a list of fs.DirEntry instead of fs.FileInfo,
// and it returns partial results in the case of an error
// midway through reading a directory.
func ReadDir(dirname string) ([]fs.FileInfo, error) {
f, err := os.Open(dirname)
if err != nil {
return nil, err
}
list, err := f.Readdir(-1)
f.Close()
if err != nil {
return nil, err
}
sort.Slice(list, func(i, j int) bool { return list[i].Name() < list[j].Name() })
return list, nil
}
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
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