1、读文件

读文件的过程

  • 文件位置
  • 打开文件
  • 读取文件内容(逐个字符读、按批读,只能按照字节切片读)
  • 关闭文件

文件路径

  • 绝对路径:程序不管在什么位置运行,打开的文件都不会变化(从根路径/盘符开始书写的路径)
  • 相对路径:与程序的位置有关(程序放置的位置、程序运行的位置)
package main

import (
	"fmt"
	"io"
	"os"
)

func main()  {
	path := "user.txt"
	file, err := os.Open(path)
	if err != nil {
		fmt.Println(err)
	} else {
		//fmt.Println(file)  // &{0xc0000b2120}  *os.File指针类型
		//var bytes []byte = make([]byte, 20)
		//n, err := file.Read(bytes)
		//fmt.Println(n ,err)
		//fmt.Println(string(bytes[:n]))
		bytes := make([]byte, 20)
		for {
			n, err := file.Read(bytes)
			if err != nil {
				if err != io.EOF {
					fmt.Println(err)
				}
				break
			} else {
				fmt.Print(string(bytes[:n]))
			}
		}
		file.Close()
	}
}

2、写文件

写文件的过程

  • 创建文件
  • 写入内容(可以写字符串或字节切片)
  • 关闭文件

示例,文件写入

package main

import (
	"fmt"
	"os"
)

func main() {
	path := "user2.txt"
	file, err := os.Create(path)
	if err != nil {
		fmt.Println(err)
	} else {
		// 写文件,会把原来的内容清空再写
		file.Write([]byte("abc123!@#"))
		file.WriteString("xyz")
		// 关闭文件
		file.Close()
	}
}

修改文件的过程

  • 追加

OpenFile的常用几种模式

os.O_WRONLY | os.O_CREATE | O_EXCL  【如果已经存在,则失败】
os.O_WRONLY | os.O_CREATE   【如果已经存在,会覆盖写,不会清空原来的文件,而是从头直接覆盖写】
os.O_WRONLY | os.O_CREATE | os.O_APPEND 【如果已经存在,则在尾部添加写】

语法

func OpenFile(name string, flag int, perm FileMode) (*File, error) 

该方法第一个参数为文件路径,第二个参数控制文件的打开方式,第三个参数控制文件模式

示例,文件追加

package main

import (
	"os"
	"strconv"
	"time"
)

func main() {
	path := "user.log"
	file, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, os.ModePerm)  // 如果已经存在,则在尾部添加写
	if err == nil {
		file.WriteString(strconv.FormatInt(time.Now().Unix(), 10))
		file.WriteString("\n")
		file.Close()
	}
}

将日志记录到文件

package main

import (
	"log"
	"os"
	"time"
)

func main() {
	path := "user.log"
	file, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, os.ModePerm)  // 如果已经存在,则在尾部添加写
	if err == nil {
		log.SetOutput(file)
		log.SetPrefix("users: ")
		log.SetFlags(log.Flags() | log.Lshortfile)
		log.Print(time.Now().Unix())
		file.Close()
	}
}

最终的文件内容效果

users: 2021/08/19 00:48:20 log.go:16: 1629388100
users: 2021/08/19 00:48:32 log.go:16: 1629388112

3、文件指针

主要是利用seek修改光标位置,用的较少

package main

import (
	"fmt"
	"os"
)

func main()  {
	file , _ := os.Open("user.txt")
	bytes := make([]byte, 100)
	n, _ := file.Read(bytes)
	fmt.Println(n, string(bytes[:n]))
	// 偏移量,相对位置
	// 文件开始 0 os.SEEK_SET
	// 当前位置 1 os.SEEK_CUR
	// 文件末尾 2 os.SEEK_END
	fmt.Println(file.Seek(0, 0))  // 偏移量、相对位置
	fmt.Println(file.Seek(0, 1))  // 查看当前偏移量
	fmt.Println(file.Seek(0, 2))  // 将指针放到文件末尾
	n, err := file.Read(bytes)
	fmt.Println(n, err, string(bytes[:n]))
	file.Close()
}

4、ioutil文件操作

4.1 readall读取文件所有内容

package main

import (
	"fmt"
	"io/ioutil"
	"os"
)

func main() {
	path := "user.txt"
	file, err := os.Open(path)
	if err != nil {
		fmt.Println(err)
	} else {
		defer file.Close()
		bytes, err := ioutil.ReadAll(file)
		fmt.Println(string(bytes), err)
	}
}

4.2 readfile直接读文件

package main

import (
	"fmt"
	"io/ioutil"
)

func main() {
	bytes, err := ioutil.ReadFile("user.txt")
	if err == nil {
		fmt.Println(string(bytes))
	}
}

4.3 writefile直接写文件

package main

import (
	"fmt"
	"io/ioutil"
	"os"
)

func main() {
	err := ioutil.WriteFile("user.txt", []byte("xxxxxxxxxxxxxxxxxxxxx"), os.ModePerm)
	fmt.Println(err)
}

5、bufio带缓冲IO

文档:https://pkg.go.dev/bufio

5.1 scanner 逐行读取

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	file, err := os.Open("user.txt")
	if err == nil {
		defer file.Close()
		i := 0
		scanner := bufio.NewScanner(file)
		for scanner.Scan() {
			fmt.Println(i, scanner.Text())
			i++
		}
	}
}

5.2 带缓冲IO reader

5.2.1 read 读

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
)

func main()  {
	file, err := os.Open("user.txt")
	if err == nil {
		defer file.Close()
		reader := bufio.NewReader(file)
		bytes := make([]byte, 5)
		for {
			n , err := reader.Read(bytes)
			if err != nil {
				if err != io.EOF {
					fmt.Println(err)
				}
				break
			} else {
				fmt.Println(n, err, string(bytes))
			}
		}
	}
}

5.2.2 readline 读

对文件的"\n"进行截断

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
)

func main() {
	file, err := os.Open("user.txt")
	if err == nil {
		defer file.Close()
		reader := bufio.NewReader(file)

		for {
			line, isPrefix, err := reader.ReadLine()
			if err != nil {
				if err != io.EOF {
					fmt.Println(err)
				}
				break
			} else {
				fmt.Println(isPrefix, err, string(line))
			}
		}
	}
}

5.2.3 readstring、readslice 读

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
)

func main() {
	file, err := os.Open("user.txt")
	if err == nil {
		defer file.Close()

		reader := bufio.NewReader(file)

		for {
			// line, err := reader.ReadSlice('\n')
			line, err := reader.ReadString('\n')
			if err != nil {
				if err != io.EOF {
					fmt.Println(err)
				}
				break
			} else {
				// fmt.Println(err, string(line))
				fmt.Println(err, line)
			}
		}
	}
}

5.3 带缓冲IO writer

带缓冲writer示例

package main

import (
	"bufio"
	"os"
)

func main() {
	file, err := os.Create("user.txt")
	if err == nil {
		defer file.Close()
		writer := bufio.NewWriter(file)

		writer.WriteString("abcdef")
		writer.Write([]byte("123456"))
		writer.Flush()
	}
}

See you ~