1. IO操作

1.1.1. 输入输出的底层原理

  • 终端其实是一个文件,相关实例如下:
    • os.Stdin:标准输入的文件实例,类型为*File
    • os.Stdout:标准输出的文件实例,类型为*File
    • os.Stderr:标准错误输出的文件实例,类型为*File

以文件的方式操作终端:

  1. package main
  2. import "os"
  3. func main() {
  4. var buf [16]byte
  5. os.Stdin.Read(buf[:])
  6. os.Stdin.WriteString(string(buf[:]))
  7. }

1.1.2. 文件操作相关API

  • func Create(name string) (file *File, err Error)
    • 根据提供的文件名创建新的文件,返回一个文件对象,默认权限是0666
  • func NewFile(fd uintptr, name string) *File
    • 根据文件描述符创建相应的文件,返回一个文件对象
  • func Open(name string) (file *File, err Error)
    • 只读方式打开一个名称为name的文件
  • func OpenFile(name string, flag int, perm uint32) (file *File, err Error)
    • 打开名称为name的文件,flag是打开的方式,只读、读写等,perm是权限
  • func (file *File) Write(b []byte) (n int, err Error)
    • 写入byte类型的信息到文件
  • func (file *File) WriteAt(b []byte, off int64) (n int, err Error)
    • 在指定位置开始写入byte类型的信息
  • func (file *File) WriteString(s string) (ret int, err Error)
    • 写入string信息到文件
  • func (file *File) Read(b []byte) (n int, err Error)
    • 读取数据到b中
  • func (file *File) ReadAt(b []byte, off int64) (n int, err Error)
    • 从off开始读取数据到b中
  • func Remove(name string) Error
    • 删除文件名为name的文件

1.1.3. 打开和关闭文件

os.Open()函数能够打开一个文件,返回一个*File和一个err。对得到的文件实例调用close()方法能够关闭文件。

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. )
  6. func main() {
  7. // 只读方式打开当前目录下的main.go文件
  8. file, err := os.Open("./main.go")
  9. if err != nil {
  10. fmt.Println("open file failed!, err:", err)
  11. return
  12. }
  13. // 关闭文件
  14. file.Close()
  15. }

1.1.4. 写文件

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. )
  6. func main() {
  7. // 新建文件
  8. file, err := os.Create("./xxx.txt")
  9. if err != nil {
  10. fmt.Println(err)
  11. return
  12. }
  13. defer file.Close()
  14. for i := 0; i < 5; i++ {
  15. file.WriteString("ab\n")
  16. file.Write([]byte("cd\n"))
  17. }
  18. }

1.1.5. 读文件

文件读取可以用file.Read()和file.ReadAt(),读到文件末尾会返回io.EOF的错误

  1. package main
  2. import (
  3. "fmt"
  4. "io"
  5. "os"
  6. )
  7. func main() {
  8. // 打开文件
  9. file, err := os.Open("./xxx.txt")
  10. if err != nil {
  11. fmt.Println("open file err :", err)
  12. return
  13. }
  14. defer file.Close()
  15. // 定义接收文件读取的字节数组
  16. var buf [128]byte
  17. var content []byte
  18. for {
  19. n, err := file.Read(buf[:])
  20. if err == io.EOF {
  21. // 读取结束
  22. break
  23. }
  24. if err != nil {
  25. fmt.Println("read file err ", err)
  26. return
  27. }
  28. content = append(content, buf[:n]...)
  29. }
  30. fmt.Println(string(content))
  31. }

1.1.6. 拷贝文件

  1. package main
  2. import (
  3. "fmt"
  4. "io"
  5. "os"
  6. )
  7. func main() {
  8. // 打开源文件
  9. srcFile, err := os.Open("./xxx.txt")
  10. if err != nil {
  11. fmt.Println(err)
  12. return
  13. }
  14. // 创建新文件
  15. dstFile, err2 := os.Create("./abc2.txt")
  16. if err2 != nil {
  17. fmt.Println(err2)
  18. return
  19. }
  20. // 缓冲读取
  21. buf := make([]byte, 1024)
  22. for {
  23. // 从源文件读数据
  24. n, err := srcFile.Read(buf)
  25. if err == io.EOF {
  26. fmt.Println("读取完毕")
  27. break
  28. }
  29. if err != nil {
  30. fmt.Println(err)
  31. break
  32. }
  33. //写出去
  34. dstFile.Write(buf[:n])
  35. }
  36. srcFile.Close()
  37. dstFile.Close()
  38. }

1.1.7. bufio

  • bufio包实现了带缓冲区的读写,是对文件读写的封装
  • bufio缓冲写数据
模式 含义
os.O_WRONLY 只写
os.O_CREATE 创建文件
os.O_RDONLY 只读
os.O_RDWR 读写
os.O_TRUNC 清空
os.O_APPEND 追加
  • bufio读数据
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "io"
  6. "os"
  7. )
  8. func wr() {
  9. // 参数2:打开模式,所有模式d都在上面
  10. // 参数3是权限控制
  11. // w写 r读 x执行 w 2 r 4 x 1
  12. file, err := os.OpenFile("./xxx.txt", os.O_CREATE|os.O_WRONLY, 0666)
  13. if err != nil {
  14. return
  15. }
  16. defer file.Close()
  17. // 获取writer对象
  18. writer := bufio.NewWriter(file)
  19. for i := 0; i < 10; i++ {
  20. writer.WriteString("hello\n")
  21. }
  22. // 刷新缓冲区,强制写出
  23. writer.Flush()
  24. }
  25. func re() {
  26. file, err := os.Open("./xxx.txt")
  27. if err != nil {
  28. return
  29. }
  30. defer file.Close()
  31. reader := bufio.NewReader(file)
  32. for {
  33. line, _, err := reader.ReadLine()
  34. if err == io.EOF {
  35. break
  36. }
  37. if err != nil {
  38. return
  39. }
  40. fmt.Println(string(line))
  41. }
  42. }
  43. func main() {
  44. re()
  45. }

1.1.8. ioutil工具包

  • 工具包写文件
  • 工具包读取文件
  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. )
  6. func wr() {
  7. err := ioutil.WriteFile("./yyy.txt", []byte("www.5lmh.com"), 0666)
  8. if err != nil {
  9. fmt.Println(err)
  10. return
  11. }
  12. }
  13. func re() {
  14. content, err := ioutil.ReadFile("./yyy.txt")
  15. if err != nil {
  16. fmt.Println(err)
  17. return
  18. }
  19. fmt.Println(string(content))
  20. }
  21. func main() {
  22. re()
  23. }

1.1.9. 例子

实现一个cat命令

使用文件操作相关知识,模拟实现linux平台cat命令的功能。

  1. package main
  2. import (
  3. "bufio"
  4. "flag"
  5. "fmt"
  6. "io"
  7. "os"
  8. )
  9. // cat命令实现
  10. func cat(r *bufio.Reader) {
  11. for {
  12. buf, err := r.ReadBytes('\n') //注意是字符
  13. if err == io.EOF {
  14. break
  15. }
  16. fmt.Fprintf(os.Stdout, "%s", buf)
  17. }
  18. }
  19. func main() {
  20. flag.Parse() // 解析命令行参数
  21. if flag.NArg() == 0 {
  22. // 如果没有参数默认从标准输入读取内容
  23. cat(bufio.NewReader(os.Stdin))
  24. }
  25. // 依次读取每个指定文件的内容并打印到终端
  26. for i := 0; i < flag.NArg(); i++ {
  27. f, err := os.Open(flag.Arg(i))
  28. if err != nil {
  29. fmt.Fprintf(os.Stdout, "reading from %s failed, err:%v\n", flag.Arg(i), err)
  30. continue
  31. }
  32. cat(bufio.NewReader(f))
  33. }
  34. }