Go的第17课——OS模块介绍,OS模块读文件

今天goland又报了错误,按照第一篇文章说的网址激活已经失效,因此换了一个方式,这里贴个链接

OS库

OS标准库实现了平台无关的编程接口。

创建文件:

1
os.Create("test.txt")

创建目录:

1
2
os.Mkdir("test", os.ModePerm)
os.MkdirAll("a/b/c/d", os.ModePerm)

两个区别就是 MkdirAll 支持多级目录创建,如果尝试用 Mkdir 去创建多级目录那么不会被执行。

删除文件:

1
2
os.Remove("test")
os.RemoveAll("a")

RemoveAll 也是一样,如果 remove 尝试删除一个非空目录,那么不会被运行。

获取工作目录:

1
os.Getwd()

修改工作目录:

1
os.Chdir("../../")

重命名文件:

1
os.Rename("src","dest")

读文件:

1
os.ReadFile("src")

写文件:

1
os.WriteFile("src",[]byte(str),os.ModePerm)

一锅乱炖写一个程序熟悉下 os 模块,其实感觉很方便,就像 Linux 那些命令一样的。

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
package main

import (
"fmt"
"os"
)

func main() {
os.Create("test.txt")
os.Mkdir("test", os.ModePerm)
os.MkdirAll("a/b/c/d", os.ModePerm)
os.Remove("test")
os.RemoveAll("a")
WD, _ := os.Getwd()
fmt.Printf("WD:%s\n", WD)
os.Chdir("../")
WD, _ = os.Getwd()
fmt.Printf("WD:%s\n", WD)
os.Chdir("WWW")
WD, _ = os.Getwd()
fmt.Printf("WD:%s\n", WD)
os.Rename("test.txt", "xia0ji233.txt")
s := "xia0ji233 233"
os.WriteFile("xia0ji233.txt", []byte(s), os.ModePerm)
b, _ := os.ReadFile("xia0ji233.txt")
str := string(b)
fmt.Printf("info: %v\n", str)
}
/*
WD:C:\Users\xia0ji233\Desktop\Home\Go\xia0ji233\WWW
WD:C:\Users\xia0ji233\Desktop\Home\Go\xia0ji233
WD:C:\Users\xia0ji233\Desktop\Home\Go\xia0ji233\WWW
info: xia0ji233 233
*/

OS File 读写操作

读文件

打开一个文件:

1
f, _ := os.Open("xia0ji233.txt")

返回的类型为 *FILE

这样打开的文件我们只能读不能写。如果要让文件可写,我们需要这样打开:

1
f2, _ := os.OpenFile("test.txt", os.O_RDWR, os.ModePerm)

这里的 O_RDWRREADWRITE 可读可写的缩写。 实际上,os.Open 内部就会调用 os.OpenFile 并把权限设置为 O_RDONLYO_CREATE 表示如果文件不存在那么创建一个空文件。那么其实,我们上面的 os.Create 函数就是直接 OpenFile 加上了一个 O_CREATE 属性。O_TRUNC 则表示如果文件存在且有内容,那么丢且并把文件转为空。

他有很多方法可以操作这个文件,比如说 f.Read([]byte b) 可以往切片 b 中写上文件内容,并且,每次读最大读的长度为切片分配的长度,f.ReadAtRead 差不多,它多了第二个参数控制文件指针从哪里开始读。

我们要用很少的内存读很大的文件的话就是需要循环读。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import (
"fmt"
"os"
)

func main() {
f, _ := os.Open("xia0ji233.txt")
buffer := make([]byte, 1)
for {
n, _ := f.Read(buffer)
if n == 0 {
break
}
fmt.Printf("%s", string(buffer))
}
}
/*
xia0ji233 233
*/

偏移读取程序:使用 f.Seek(offset,whence) ,第一个参数表示偏移,第二个参数表示从哪里开始偏移。

0表示文件开头,1表示文件当前位置,2表示文件末尾。

比如当前读到第5个字节了(第五个还没读),那么 f.Seek(1,1) 就是直接移动到第六个字节上面,f.Seek(1,0) 就会直接移动到第二个字节上面(第一个字节往后一个字节是第二个字节)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main

import (
"fmt"
"os"
)

func main() {
f, _ := os.OpenFile("xia0ji233.txt", os.O_RDWR, 0755)
buffer := make([]byte, 2)
f.Seek(1, 0)
f.Read(buffer)
fmt.Printf("%s\n", string(buffer))
}
/*
ia
*/

本节课学习的示例程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import (
"fmt"
"os"
)

func main() {
f, _ := os.Open("xia0ji233.txt")
fmt.Printf("f.Name(): %v\n", f.Name())
var b []byte = make([]byte, 1024)
n, _ := f.Read(b)
fmt.Printf("info: %v\n", string(b))
f2, _ := os.OpenFile("test.txt", os.O_RDWR|os.O_TRUNC, 0755)
s := string(b[:n])
f2.WriteString(s)
f2.Close()
}
/*
f.Name(): xia0ji233.txt
info: xia0ji233 233
*/

读取目录

使用 os.ReadDir 去读取一个目录下面的内容,返回一个文件类切片,可以使用 for range 去遍历。

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
package main

import (
"fmt"
"os"
)

func main() {
de, _ := os.ReadDir(".")
for _, v := range de {
fmt.Printf("Name:%v\n", v.Name())
fmt.Printf("attr:%v\n", v.IsDir())
}
}
/*
Name:DAO
attr:true
Name:go.mod
attr:false
Name:main.go
attr:false
Name:test.txt
attr:false
Name:xia0ji233.txt
attr:false
*/