打开和关闭文件

在Go语言中使用os.Open()可以打开一个文件,返回一个文件指针*file和错误信息err,对得到的文件指针调用close()方法即可关闭文件。

如下:

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. )
  6. func main() {
  7. file, _ := os.Open("./main.go")
  8. fmt.Printf("%T\n", file)
  9. file.Close()
  10. }

为了防止文件忘记关闭,我们通常使用defer注册文件关闭语句。

如下:

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. )
  6. func main() {
  7. file, _ := os.Open("./main.go")
  8. fmt.Printf("%T\n", file)
  9. defer file.Close()
  10. }

读取文件

file.read()

read方法定义如下:

  1. func (f *File) Read(b []byte) (n int, err error)

该方法接受一个字节类型的参数,返回读取的字节数和可能的错误,读到文件末尾会返回0io.EOF

如下:

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. )
  6. func main() {
  7. file, err := os.Open("./main.go")
  8. if err != nil {
  9. fmt.Printf("File Open failed.err:%s\n", err)
  10. return
  11. }
  12. defer file.Close()
  13. // 定义读取的字节数
  14. tmp := make([]byte, 128)
  15. // 按字节读取文件
  16. n, err := file.Read(tmp)
  17. if err != nil {
  18. fmt.Printf("File Read Failed.err:%s\n", err)
  19. return
  20. }
  21. // 打印读取的字节数
  22. fmt.Println(n)
  23. // 打印读取的内容
  24. fmt.Println(string(tmp[:n]))
  25. }

上面这种读取方式是按设定的字节读取,如果文本中总字节数少于设定的,那么就可以把文本全部读取出来,如果文本总字节数大于设定的字节数,那么文本就不能被全部读取。

这个时候可以使用循环来读取所有文本,如下:

  1. package main
  2. import (
  3. "fmt"
  4. "io"
  5. "os"
  6. )
  7. func main() {
  8. file, err := os.Open("./main.go")
  9. if err != nil {
  10. fmt.Printf("File Open failed.err:%s\n", err)
  11. return
  12. }
  13. defer file.Close()
  14. // 定义读取的字节数
  15. tmp := make([]byte, 128)
  16. for {
  17. // 按字节读取文件
  18. n, err := file.Read(tmp)
  19. // 如果文件已经读完了,就退出
  20. if err == io.EOF {
  21. // fmt.Printf("文件读完了\n")
  22. break
  23. }
  24. if err != nil {
  25. fmt.Printf("File Read Failed.err:%s\n", err)
  26. return
  27. }
  28. // 打印读取的内容
  29. fmt.Print(string(tmp[:n]))
  30. }
  31. }

bufio读取文件

bufio是带缓存功能的I/O操作。用其读取文件的示例如下:

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "io"
  6. "os"
  7. )
  8. func main() {
  9. // 打开文件
  10. file, err := os.Open("./main.go")
  11. if err != nil {
  12. fmt.Printf("Open File Failed.err:%s\n", err)
  13. return
  14. }
  15. defer file.Close()
  16. // 返回一个新的reader,用NewReader有默认大小
  17. reader := bufio.NewReader(file)
  18. // 用循环逐行读取文件
  19. for {
  20. line, err := reader.ReadString('\n')
  21. if err == io.EOF {
  22. // fmt.Printf("File Has Been Read\n")
  23. break
  24. }
  25. if err != nil {
  26. fmt.Printf("Read File Failed.err:%s\n", err)
  27. }
  28. fmt.Print(line)
  29. }
  30. }

上面是用的bufio.NerReader()来获取一个新的reader,再用这个对象来读取文件的。除此之外还可以使用bufio.NewReaderSize来获取一个新的reader,不同之处在于NewReaderSize可以设置缓冲区的大小,语法如下:

  1. reader := bufio.NewReaderSize(fileObj, size)

ioutil读取整个文件

io/ioutil包的ReadFile方法能够读取完整的文件,只需要将文件名作为参数传入。

  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. )
  6. func main() {
  7. content, err := ioutil.ReadFile("./main.go")
  8. if err != nil {
  9. fmt.Printf("Read File Failed.err:%s\n", err)
  10. return
  11. }
  12. fmt.Println(string(content))
  13. }

写入文件

os.OpenFile()函数能够以指定模式打开文件,从而实现文件写入相关功能。

  1. func OpenFile(name string, flag int, perm FileMode) (*File, error) {
  2. ...
  3. }

其中:

name:要打开的文件名 flag:打开文件的模式。 模式有以下几种:

含义 模式
只写 os.O_WRONLY
创建文件 os.O_CREATE
只读 os.O_RDONLY
读写 os.O_RDWR
清空 os.O_TRUNC
追加 os.O_APPEND

perm:文件权限,一个八进制数。r(读)04,w(写)02,x(执行)01。

比如:

  1. file,err := os.OpenFile("xx.txtx",os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)

Write和WriteString

Write写入的是字节切片数据,WriteString写入的是字符串数据。

如下:

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. )
  6. func main() {
  7. file, err := os.OpenFile("a.txt", os.O_APPEND|os.O_CREATE, 0644)
  8. if err != nil {
  9. fmt.Printf("Open File Failed.err:%s\n", err)
  10. return
  11. }
  12. defer file.Close()
  13. // 写入
  14. str := "牛逼的Go语言\n"
  15. // 用Write写入
  16. file.Write([]byte(str))
  17. // 用WriteString写入
  18. file.WriteString(str)
  19. }

bufio写入文件

使用bufio.NewWriter()写入文件,需要在最后Flush()

如下:

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "os"
  6. )
  7. func main() {
  8. file, err := os.OpenFile("b.txt", os.O_APPEND|os.O_CREATE, 0644)
  9. if err != nil {
  10. fmt.Printf("Open File Failed.err:%s\n", err)
  11. return
  12. }
  13. defer file.Close()
  14. // 用bufio.NewWrite返回一个writer
  15. writer := bufio.NewWriter(file)
  16. writer.WriteString("这是一个bufio的写入测试")
  17. writer.Flush()
  18. }

同理除了使用NewWriter,还可以使用NewWriterSize

ioutil写入文件

前面介绍ioutil.ReadFile可以读取整个文件,另外ioutil.WriterFile也可以一次性将内容写入文件。

语法如下:

  1. err := ioutil.WriterFile("xxx.txt", []byte(str), 0644)

如下:

  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. )
  6. func main() {
  7. str := `
  8. 融融的三月,万物尽苏醒
  9. 蜿蜒曲折的小路承载着儿时的记忆
  10. 鸟儿在树梢吟唱,歌颂着新春好光景
  11. 阳光明媚,和着泥土和花香
  12. 舒展手臂抱向天空,拥抱朵朵云彩
  13. 大地又重新充满了生机。
  14. `
  15. err := ioutil.WriteFile("./c.txt", []byte(str), 0644)
  16. if err != nil {
  17. fmt.Printf("Write File Failed.err:%s\n", err)
  18. return
  19. }
  20. }

日志库

需求

  • 支持往不同地方写日志
  • 日志分级别
    • Debug
    • Trace
    • Info
    • Warning
    • Error
    • Fatal
  • 日志支持开关控制
  • 日志记录包含时间、行号、文件名、日志级别、日志信息
  • 日志文件要切割
    • 按大小切割
    • 按时间切割