读取


读取-只读模式

此模式仅可读取文件

  1. // 只读打开
  2. f, err := os.Open("./book.html")
  3. if err != nil {
  4. fmt.Println(err.Error())
  5. }
  6. // 延迟关闭文件句柄
  7. defer f.Close()
  8. readFile := func() []byte {
  9. // 读取文件内容
  10. var content []byte
  11. tmp := make([]byte, 128) // 临时变量
  12. for {
  13. // 读取值到临时变量
  14. // byteNum 读取到的字节数
  15. byteNum, err := f.Read(tmp)
  16. if err == io.EOF {
  17. fmt.Println("文件读取结束")
  18. break
  19. }
  20. // 这里如果使用tmp[]..., 可以会写入零值数据(因为临时存储区大小和文件结尾可能不一致)
  21. content = append(content, tmp[:byteNum]...)
  22. }
  23. return content
  24. }
  25. fmt.Printf("文件内容: \n%s\n", readFile())

虽然叫只读模式,但是方法内调用的是OpenFile(name, O_RDONLY, 0),详见👇🏻

读取-通用模式

此模式是可自由设置执行的操作文件权限
常用flag:

变量 作用
os.O_RDONLY 只读模式
os.O_WRONLY 只写模式
os.O_RDWR 读和写模式
os.O_APPEND 插入模式
os.O_CREATE 创建模式(未找到文件会创建)
os.O_SYNC 同步IO模式(阻塞模式)
os.O_EXCL 与O_CREATE一起使用,文件不能存在
多模式 os.O_WRONLY | os.O_CREATE
  1. // filename 文件名
  2. // flag: 执行的操作(os/file.go 73行定义)
  3. // filemode: 文件权限(仅在linux及类linux平台使用, os/types.go 35行定义 )
  4. f, err := os.OpenFile("./deme.pu", os.O_RDONLY, os.ModePerm)
  5. if err != nil {
  6. fmt.Println(err.Error())
  7. }
  8. defer f.Close()
  9. fmt.Printf("%s\n", readFile(f))

使用bufio读取文件

  1. f, err := os.Open("./demo.txt")
  2. if err != nil {
  3. fmt.Println(err.Error())
  4. }
  5. defer f.Close()
  6. reader := bufio.NewReader(f)
  7. for {
  8. line, isPrefix, err := reader.ReadLine()
  9. if err == io.EOF {
  10. fmt.Println("文件读完了")
  11. break
  12. }
  13. if err != nil {
  14. fmt.Printf("文件读取失败%s\n", err.Error())
  15. return
  16. }
  17. fmt.Println(string(line), isPrefix)
  18. }

bufio是在file的基础上封装了一层API,并且支持更多功能,比如上面代码会删除换行符

使用ioutil读取整个文件

  1. f, err := ioutil.ReadFile("./test.txt")
  2. if err != nil {
  3. log.Fatalln(err.Error())
  4. }
  5. fmt.Println(string(f))

ioutil.ReadFile()方法可以将整个文件读取至变量,建议在读取小文件时使用(大文件容易造成内存泄露)

写入


  1. f, _ := os.OpenFile("./deme.txt", os.O_WRONLY|os.O_CREATE, os.ModePerm)
  2. defer f.Close()
  3. byteNum, _ := f.Write([]byte("你好"))
  4. fmt.Printf("write byte %d\n",byteNum)

以上代码使用os包的OpenFile函数,通过设置写入创建flag来在文件没有时创建并写入文件

  1. f, _ := os.OpenFile("./deme.txt", os.O_WRONLY|os.O_APPEND, os.ModePerm)
  2. defer f.Close()
  3. byteNum, _ := f.Write([]byte("你好"))
  4. fmt.Printf("write byte %d\n",byteNum)

使用bufio.NewWriter写入

  1. f, _ := os.OpenFile("./demo.txt", os.O_WRONLY, os.ModePerm)
  2. defer f.Close()
  3. bfw := bufio.NewWriter(f)
  4. bfw.Write([]byte("hello\n"))
  5. bfw.WriteString("你好\n")
  6. bfw.Flush()

使用bufio可以将写入缓存中,然后通过Flush方法写入文件

使用ioutil.WriteFile写入

  1. err := ioutil.WriteFile("./tmp.txt", []byte("world"), os.ModePerm)
  2. if err != nil {
  3. log.Fatalf("写入失败: %s", err.Error())
  4. }

使用ioutil同样可以写入文件,并且在文件不存在时帮你创建

使用ioutil.TmpDir创建临时文件

  1. name, _ := ioutil.TempDir("./tmp/", "dong_")
  2. defer func(name string) {
  3. err := os.Remove(name)
  4. if err != nil {
  5. log.Fatalln("删除失败")
  6. } else {
  7. log.Println("删除成功")
  8. }
  9. }(name)
  10. fmt.Println(name)
  11. time.Sleep(10 * time.Second)

临时目录可以临时存储一些文件,并在不再使用后删除

练习


写个cp命令

  1. var srcFile string
  2. var dstPath string
  3. _, err := fmt.Scan(&srcFile, &dstPath)
  4. if err != nil {
  5. log.Fatalln(err.Error())
  6. return
  7. }
  8. src, err := os.Open(srcFile)
  9. if err != nil {
  10. log.Fatalf("Open file failed : %s", err.Error())
  11. }
  12. defer src.Close()
  13. dst, err := os.OpenFile(dstPath+src.Name(), os.O_CREATE|os.O_EXCL|os.O_WRONLY, os.ModePerm)
  14. if err != nil {
  15. log.Fatalln(err.Error())
  16. }
  17. _, err = io.Copy(dst, src)
  18. if err != nil {
  19. log.Fatalf("Copy error %s", err.Error())
  20. }

通过fmt.Scan获取命令行参数,通过io.Copy方法将流拷贝至新文件,因为os.OpenFile实现了io.Writerio.Reader接口