1.文件操作

题外话:标准库怎么访问?

  • 两种
    • 到Go文件中打开
      os包--文件操作 - 图1
      os包--文件操作 - 图2
    • ctrl+点击 某函数
  • 官网
    os包--文件操作 - 图3

1.1、文件与目录

创建

作用 语法/实例说明
create 创建文件 os包--文件操作 - 图4
底层是OpenFile,实例见下方
CreateTemp 创建临时文件 os包--文件操作 - 图5 结果 os包--文件操作 - 图6
1. ""是表示是临时文件,temp是前缀(temp2896…..)
2. 创建地址在临时目录地址(系统自设的)
3. 临时文件有什么作用???
创建目录 <font style="color:rgb(0,0,0);">Mkdir</font> 创建单个目录 os包--文件操作 - 图7 os包--文件操作 - 图8地址在项目目录下
<font style="color:rgb(0,0,0);">MkdirAll</font> 创建多层目录 os包--文件操作 - 图9 os包--文件操作 - 图10地址在项目目录下
NewFile ???描述 **<font style="color:rgb(0,0,128);">func </font>**<font style="color:rgb(0,0,0);">NewFile(fd </font><font style="color:rgb(0,0,128);">uintptr</font><font style="color:rgb(0,0,0);">, name </font><font style="color:rgb(0,0,128);">string</font><font style="color:rgb(0,0,0);">) *File </font> 根据文件描述符创建相应的文件,返回一个文件对象

:::info create实例

:::

os包--文件操作 - 图11
结果
os包--文件操作 - 图12

作用:根据提供的文件名创建新的文件,返回一个文件对象,默认权限是 0666 的文件,返回的文件对象是可读写的。解析如下
  1. 文件格式——包含在名字里(我猜的,目前只创建过文本文件)
  2. 地址在项目地址里
  3. 若已存在同名文件名,再创建,就会覆盖旧文件重新创建
    OpenFile("a.txt", os.O_RDWR|os.O_CREATE|O_TRUNC,0666)等价于create("a.txt")其中O_TRUNC表示覆盖同名旧文件的意思)

删除文件

remove

  • 删除文件**<font style="color:rgb(0,0,128);">func </font>**<font style="color:rgb(0,0,0);">Remove(name </font><font style="color:rgb(0,0,128);">string</font><font style="color:rgb(0,0,0);">) Error</font>
    os包--文件操作 - 图13
  • 删除目录以及其包含的东西 **<font style="color:rgb(0,0,128);">func </font>**<font style="color:rgb(0,0,0);">RemoveAll(name </font><font style="color:rgb(0,0,128);">string</font><font style="color:rgb(0,0,0);">) Error</font>
    os包--文件操作 - 图14

?获取和修改工作目录

这里的临时目录是什么???干什么用的???
作用 语法/实例解析
getWd() 获得工作目录 os包--文件操作 - 图15 结果(获得地项目地址) os包--文件操作 - 图16
chWd() 修改工作目录 os包--文件操作 - 图17
TempDir() 获得临时目录 os包--文件操作 - 图18 结果 os包--文件操作 - 图19

重命名文件

注意,必须是Rename,不能是rename

os包--文件操作 - 图20

黑马实例分析

:::info 写文件

:::

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. )
  6. func main() {
  7. fout, err := os.Create("./xxx.txt") //新建文件
  8. //fout, err := os.OpenFile("./xxx.txt", os.O_CREATE, 0666)
  9. if err != nil {
  10. fmt.Println(err)
  11. return
  12. }
  13. defer fout.Close() //main 函数结束前, 关闭文件
  14. for i := 0; i < 5; i++ {
  15. outstr := fmt.Sprintf("%s:%d\n", "Hello go", i)
  16. fout.WriteString(outstr) //写入 string 信息到文件
  17. fout.Write([]byte("abcd\n")) //写入 byte 类型的信息到文件
  18. }
  19. }

os包--文件操作 - 图21

结果:

os包--文件操作 - 图22

:::info 读文件

:::

读文件,要先打开,Open方法,给到fin,再读取read,给到buf,n:_:=fin.Read(buf),n=0时就表示读完了

  1. func main() {
  2. fin, err := os.Open("./xxx.txt") //打开文件
  3. if err != nil {
  4. fmt.Println(err)
  5. }
  6. defer fin.Close()
  7. buf := make([]byte, 1024) //开辟 1024 个字节的 slice 作为缓冲
  8. for {
  9. n, _ := fin.Read(buf) //读文件
  10. if n == 0 { //0 表示已经到文件结束
  11. break
  12. }
  13. fmt.Println(string(buf)) //输出读取的内容
  14. }
  15. }

os包--文件操作 - 图23

:::info 拷贝文件

:::

  1. package main
  2. import (
  3. "fmt"
  4. "io"
  5. "os"
  6. )
  7. func main() {
  8. args := os.Args //获取用户输入的所有参数
  9. /*如果用户没有输入,或参数个数不够,则调用该函数提示用户
  10. (需要三个参数,可执行程序一个 xxx,源文件 src,目的文件dst)
  11. */
  12. if args == nil || len(args) != 3 {
  13. fmt.Println("useage : xxx srcFile dstFile")
  14. return
  15. }
  16. srcName := args[1] //获取输入的第一个参数,
  17. dstName := args[2] //获取输入的第二个参数
  18. fmt.Printf("srcName = %s, dstName = %s\n", srcPath, dstPath)
  19. if srcName == dstName {
  20. fmt.Println("源文件和目的文件名字不能相同")
  21. return
  22. }
  23. srcFile, err1 := os.Open(srcName) //打开源文件
  24. if err1 != nil { //源文件在程序之前已存在,不创建,前面只是命个名
  25. fmt.Println(err1)
  26. return
  27. }
  28. dstFile, err2 := os.Create(dstName) //创建目的文件
  29. if err2 != nil {
  30. fmt.Println(err2)
  31. return
  32. }
  33. buf := make([]byte, 1024) //切片缓冲区
  34. for { //从源文件读取内容,n 为读取文件内容的长度
  35. n, err := srcFile.Read(buf)
  36. if err != nil && err != io.EOF {
  37. fmt.Println(err)
  38. break
  39. }
  40. if n == 0 {
  41. fmt.Println("文件处理完毕")
  42. break
  43. }
  44. //切片截取
  45. tmp := buf[:n]
  46. //把读取的内容写入到目的文件
  47. dstFile.Write(tmp)
  48. }
  49. //关闭文件
  50. srcFile.Close()
  51. dstFile.Close()
  52. }

os包--文件操作 - 图24

os包--文件操作 - 图25

运行结果:

拷贝的是一个MP4文件

os包--文件操作 - 图26

注意点:

args := os.Args 需要三个参数,可执行程序一个 xxx,源文件 src,目的文件ds
os包--文件操作 - 图27

1.2、File文件读操作

打开、关闭文件

作用 语法→实例
Open 只读打开 + 语法 **<font style="color:rgb(0,0,128);">func </font>**<font style="color:rgb(0,0,0);">Open(name </font><font style="color:rgb(0,0,128);">string</font><font style="color:rgb(0,0,0);">) (file *File, err Error) </font> 该方法打开一个名称为 name 的文件,但是是只读方式,内部实现其实调用了 OpenFile
+ 实例 os包--文件操作 - 图28
- 若不存在结果是(注意这里用println的话,结果是一堆编码???): os包--文件操作 - 图29
- 若存在这里获得的结果(由于是打印名字,<font style="color:rgb(0,0,0);">f.Name()</font>): os包--文件操作 - 图30
+ 若直接打印 (我发现每次执行结果都不一样,不知道为什么???os包--文件操作 - 图31 结果 os包--文件操作 - 图32
OpenFile 根据第二个参数,打开后读写 or 创建后打开 + 语法 **<font style="color:rgb(0,0,128);">func </font>**<font style="color:rgb(0,0,0);">OpenFile(name </font><font style="color:rgb(0,0,128);">string</font><font style="color:rgb(0,0,0);">, flag </font><font style="color:rgb(0,0,128);">int</font><font style="color:rgb(0,0,0);">, perm </font><font style="color:rgb(0,0,128);">uint32</font><font style="color:rgb(0,0,0);">) (file *File, err Error) </font> 打开名称为 name 的文件,flag 是打开的方式,只读、读写等,perm 是权限
+ 实例
- os.O_RDWR表示可读可写;os.O_CREATE表示若无则创建;755是一个权限(???) os包--文件操作 - 图33
- `OpenFile(“a.txt”, os.O_RDWR
os.O_CREATE O_TRUNC,0666)等价于create(“a.txt”)`
关闭 是一个方法,当不访问的时候,把他关闭,以保证之后读写等操作不会出错 f.close()(f是open后读取的文件)

读文件

作用 语法→实例
ReadFile ???第一节 + 语法 os包--文件操作 - 图34
+ 实例 os包--文件操作 - 图35
Read 只读不写 + **<font style="color:rgb(0,0,128);">func </font>**<font style="color:rgb(0,0,0);">(file *</font><font style="color:rgb(0,0,128);">File</font><font style="color:rgb(0,0,0);">) Read(b []</font><font style="color:rgb(0,0,128);">byte</font><font style="color:rgb(0,0,0);">) (n </font><font style="color:rgb(0,0,128);">int</font><font style="color:rgb(0,0,0);">, err Error) </font> file文件的内容,读取数据到 变量b 中
+ 实例 os包--文件操作 - 图36
1. 打开文件
2. 设置缓冲区+读文件读进缓冲区buf,且返回得读取的字符数目n 和 error
3. 打印
实际缓冲区不可能设置的无限大,在不知道文件大小的前提下,可以使用for无限循环包住2 3 步,用<font style="color:rgb(0,0,0);">if err == io.EOF{break}</font>来结束 ,<font style="color:rgb(0,0,0);">io.EOF</font>表示末尾
ReadAt 从指定从某个字节开始读 + 语法:**<font style="color:rgb(0,0,128);">func </font>**<font style="color:rgb(0,0,0);">(file *</font><font style="color:rgb(0,0,128);">File</font><font style="color:rgb(0,0,0);">) ReadAt(b []</font><font style="color:rgb(0,0,128);">byte</font><font style="color:rgb(0,0,0);">, off </font><font style="color:rgb(0,0,128);">int64</font><font style="color:rgb(0,0,0);">)(n </font><font style="color:rgb(0,0,128);">int</font><font style="color:rgb(0,0,0);">, err Error)</font> 从 off 开始读取数据到 b 中
+ 实例 os包--文件操作 - 图37 结果: os包--文件操作 - 图38 b,txt文件: os包--文件操作 - 图39
ReadDir 读取目录 或者叫,遍历某个目录 os包--文件操作 - 图40
os包--文件操作 - 图41
结果
os包--文件操作 - 图42
os包--文件操作 - 图43

注意:要求查询的目录,必须从项目地址之下的(不包含项目地址,因此不可读取所有项目地址下的所有目录),一层一层下去,"a/b/c"
seek辅助+Read 告诉从指定位置开始读 os包--文件操作 - 图44
结果: os包--文件操作 - 图45 os包--文件操作 - 图46offset是起点,终点取决于buf容量,后面的0确实不知道是什么???

1.3、File写文件操作

作用 语法→实例
writeFile ??? 实例 os包--文件操作 - 图47
write 写字节数组/切片 + **<font style="color:rgb(0,0,128);">func </font>**<font style="color:rgb(0,0,0);">(file *</font><font style="color:rgb(0,0,128);">File</font><font style="color:rgb(0,0,0);">) Write(b []</font><font style="color:rgb(0,0,128);">byte</font><font style="color:rgb(0,0,0);">) (n </font><font style="color:rgb(0,0,128);">int</font><font style="color:rgb(0,0,0);">, err Error)</font> 写入 byte 类型的信息到文件
+ 实例 os包--文件操作 - 图48
writeString 写字符串 + **<font style="color:rgb(0,0,128);">func </font>**<font style="color:rgb(0,0,0);">(file *</font><font style="color:rgb(0,0,128);">File</font><font style="color:rgb(0,0,0);">) WriteString(s </font><font style="color:rgb(0,0,128);">string</font><font style="color:rgb(0,0,0);">) (ret </font><font style="color:rgb(0,0,128);">int</font><font style="color:rgb(0,0,0);">, err Error)</font> 写入 string 信息到文件
+ 实例 os包--文件操作 - 图49
writeAt 在某个位置开始写 + **<font style="color:rgb(0,0,128);">func </font>**<font style="color:rgb(0,0,0);">(file *</font><font style="color:rgb(0,0,128);">File</font><font style="color:rgb(0,0,0);">)WriteAt(b []</font><font style="color:rgb(0,0,128);">byte</font><font style="color:rgb(0,0,0);">, off </font><font style="color:rgb(0,0,128);">int64</font><font style="color:rgb(0,0,0);">)(n </font><font style="color:rgb(0,0,128);">int</font><font style="color:rgb(0,0,0);">, err Error)</font> 在指定位置开始写入 byte 类型的信息
+ 实例 os包--文件操作 - 图50

1.4、总结

文件
创建 创建文件Create
删除 删除文件Remove
重命名文件 rename
所有文件都要:打开→写入/只读→关闭
打开文件 Open、OpenFile
写文件 WriteFile、Write、WriteAt、WriteString
读文件 ReadFile、Read、ReadAt
关闭文件 Close
目录
创建 创建单个目录Mkdir、创建多层目录MkdirAll
删除 删除目录及包含的一切RemoveAll
获取和修改工作目录 获取工作目录Getwd、修改工作目录Chdir、获得临时目录TempDir
遍历目录 ReadDir
  1. package main
  2. import (
  3. "fmt"
  4. "io"
  5. "os"
  6. )
  7. func CreatFile(){
  8. f, err := os.Create("a.txt")
  9. if err != nil {
  10. fmt.Println(err)
  11. }else {
  12. fmt.Println(f)
  13. }
  14. }
  15. func CreateDir(){
  16. err := os.Mkdir("a", os.ModePerm)
  17. if err != nil {
  18. println(err)
  19. }
  20. }
  21. func CreateDirAll(){
  22. err := os.MkdirAll("a/b/c", os.ModePerm)
  23. if err != nil {
  24. println(err)
  25. }
  26. }
  27. func RemoveFile(){
  28. err := os.Remove("a.txt")
  29. if err != nil {
  30. println(err)
  31. }
  32. }
  33. func RemoveFileAll(){
  34. err := os.RemoveAll("a")
  35. if err != nil {
  36. println(err)
  37. }
  38. }
  39. //获取和修改工作目录
  40. func GetWd(){
  41. dir, err := os.Getwd()
  42. if err != nil {
  43. println(err)
  44. }else {
  45. println(dir)
  46. }
  47. }
  48. func TempDir(){
  49. dir := os.TempDir()
  50. println(dir)
  51. }
  52. //重命名
  53. func rename() {
  54. err := os.Rename("a.txt", "b.txt")
  55. if err != nil {
  56. println(err)
  57. }
  58. }
  59. //打开、关闭文件
  60. func Open() {
  61. f, err := os.Open("b.txt")
  62. if err != nil {
  63. fmt.Printf("err:%v\n", err)
  64. }else{
  65. fmt.Printf("f:%v\n", f)
  66. f.Close()
  67. }
  68. }
  69. func OpenFile(){
  70. f, err := os.OpenFile("a.txt", os.O_RDWR|os.O_CREATE, 755)
  71. if err != nil {
  72. println(err)
  73. }else {
  74. println(f.Name())
  75. f.Close()
  76. }
  77. }
  78. //读文件
  79. //这个read没反应,也没报错,效果还没实现
  80. func ReadOps(){
  81. f, _:= os.Open("b.txt")
  82. for{
  83. buf := make([]byte, 10)
  84. n, err := f.Read(buf)
  85. if err != io.EOF {
  86. break
  87. }
  88. fmt.Printf("n:%v\n", n)
  89. fmt.Printf("string(buf):%v\n", string(buf))
  90. }
  91. f.Close()
  92. }
  93. func ReadAt(){
  94. f, _ := os.Open("b.txt")
  95. buf := make([]byte, 10)
  96. n, err := f.ReadAt(buf, 3)
  97. if err != nil {
  98. println(err)
  99. }
  100. fmt.Printf("n:%v\n", n)
  101. fmt.Printf("buf:%v\n", string(buf))
  102. }
  103. func ReadDir(){
  104. dir, _ := os.ReadDir("a")
  105. for _, v := range dir {
  106. fmt.Printf("v.IdDir():%v\n", v.IsDir())
  107. fmt.Printf("v.Name():%v\n", v.Name())
  108. }
  109. }
  110. func ReadSeek(){
  111. f, _ := os.Open("b.txt")
  112. f.Seek(3,0)
  113. buf:= make([]byte, 20)
  114. n, _ := f.Read(buf)
  115. fmt.Printf("n:%v\n", n)
  116. fmt.Printf("String(buf):%v\n", string(buf))
  117. f.Close()
  118. }
  119. //写文件
  120. func Write(){
  121. f, _ := os.OpenFile("c.txt",os.O_RDWR|os.O_APPEND, 0775)
  122. f.Write([]byte("!!!!!!"))
  123. f.Close()
  124. }
  125. func WriteString(){
  126. f, _ := os.OpenFile("c.txt",os.O_RDWR|os.O_APPEND, 0775)
  127. f.WriteString("that is good")
  128. f.Close()
  129. }
  130. func WriteAt(){
  131. f, _ := os.OpenFile("c.txt",os.O_RDWR, 0775)
  132. f.WriteAt([]byte("_this way_"), 3)
  133. f.Close()
  134. }
  135. func main(){
  136. WriteAt()
  137. }

注意点

  • 读取的结果很多时候都需要进行转化,
    • string()
    • f.Name()
  • 文件操作
    • 打开就可以与创建合并,但注意打开若进入循环就会反复从头开始
    • 写入和只读,可以对位置、内容操作
  • 权限不是很懂???,0775,0666,755
  • OpenFile具有很大的自由度,可以有各种命令嵌入
    • os.O_RDWR表示可读写
    • os.O_CREATE表示若没有这个文件就创建
    • os.O_TRUNC表示覆盖同名旧文件的意思
    • os.O_APPEND表示在旧文件上追加新内容

技巧

  • if有智能按键
  • 变量/值.Print——生成打印语句
  • 变注释
  • 值.var——创建了它,并且有返回err(是根据函数返回值自动创建吗?)
  • pkgm直接创建main包声明和main函数(没成功)

?2.进程相关的操作

  • 设置进程的属性(一个进程,一个父进程)
    os包--文件操作 - 图51
  • 开始一个新进程(???这种格式,没见过)
    os包--文件操作 - 图52
    os包--文件操作 - 图53
  • 通过进程id查找进程
    os包--文件操作 - 图54
  • 杀死进程→等待进程退出,返回进程状态(告知已退出)
    os包--文件操作 - 图55???方法里,嵌入一个匿名函数?

以上代码的结果
os包--文件操作 - 图56

  1. package main
  2. import (
  3. "os"
  4. "fmt"
  5. )
  6. func main(){
  7. //获取当前进程
  8. fmt.Printf("os.Getpid():%v\n", os.Getpid())
  9. fmt.Printf("os.Getppid():%v\n", os.Getppid())
  10. //设置新的进程属性
  11. attr := &os.ProcAttr{
  12. Files: []*os.File{os.stdin, os.Stdout, os.Stderr},
  13. Env: os.Environ(),
  14. }
  15. p, err := os.StartProcess("C:\\Windows\\System32\\notepad.exe", []string{"C:\\Windows\\System32\\notepad.exe"
  16. }, "D:\\a.txt", attr)
  17. }

3、获取命令行参数

通过os.Args获得用户传递的参数,注意所有的参数,都是以字符串的方式进行传递(也就是说,os.Args是一个字符串型切片[]string

注意:

  1. 切片第一位往往是执行命令
  2. 空格不算进切片

实例1
os包--文件操作 - 图57
os包--文件操作 - 图58

实例2

用go build运行文件,形成可执行程序main.exe,再输入参数
os包--文件操作 - 图59