os 包的 File 结构体 封装了所有文件相关操作。文档:https://studygolang.com/pkgdoc
1.1.1. 一、以缓冲的方式读取文件。
当我们读取一个特别大的文件,不能全部读取到内存里面,需要以缓冲的方式读取文件。就是读取文件的一部分内容,处理完再读取下一部分。
代码如下:
//以read-only 方式打开文件。返回文件指针。如果打开错误,返回err错误
file, err := os.Open("C:/Users/Administrator/Desktop/test.txt")
if err != nil {
fmt.Println("打开文件错误")
}
//函数执行完成后,关闭文件
defer file.Close()
// 创建一个reader,默认带4096个字节的缓冲。
reader := bufio.NewReader(file)
//循环读取文件的内容
for {
// 读到一个换行\n就结束。当前只读取一行。存储到str变量。
str, readErr := reader.ReadString('\n')
fmt.Print(str) //输出读取到的内容
if readErr == io.EOF { // io.EOF 表示文件末尾
fmt.Println("读取完毕。。。。")
break
}
}
使用了几个API:
- 打开文件:os包的 os.Open 函数。
- 关闭文件:os包中 File 结构体的 Close() 方法。
- 创建缓冲:bufio 包的 NewReader 函数。
- 读取文件:bufio 包中 Reader 结构体的 ReadString 方法。
注意:
str, readErr := reader.ReadString('\n')
表示读到一个换行\n就结束读取。如果换成一个其他字符,比如:reader.ReadString('a')
本次读取就会读到'a'就结束读取,如果'a'
在文件中不存在,那就会读取文件的全部内容。
1.1.2. 二、一次性读取文件所有内容。
使用 ioutil 包的 ReadFile 函数 (ioutil.ReadFile),可以把文件一次性读取到内存中。这种方式适合文件内容比较小的情况。
func main() {
// 一次性读取文件,适合小文件。文件的open、close隐藏在里面了。
content, err := ioutil.ReadFile("C:/Users/Administrator/Desktop/test.txt")
if err != nil {
fmt.Println("读取文件错误。。。")
}
// []byte 转换为string
str := string(content)
fmt.Println(str)
}
说明:ReadFile(filename string) ([]byte, error) 返回一个[]byte,需要转换为字符串。并且文件的open、close隐藏在里面了。
1.1.3. 三、示例,读取文件统计字符的个数。
读取一个文件,统计总共有多少英文个数、数字的个数、空格的个数、其它字符的个数。示例如下:
//定义一个结构体,用于保存统计结果
type CharCount struct {
ChCount int // 记录英文个数
NumCount int // 记录数字的个数
SpaceCount int // 记录空格的个数
OtherCount int // 记录其它字符的个数
}
func main() {
file, err := os.Open( "C:/Users/Administrator/Desktop/test.txt")
if err != nil {
fmt.Printf("打开文件 err=%v\n", err)
return
}
defer file.Close()
//定义个 CharCount 实例
var count CharCount
//创建一个 Reader
reader := bufio.NewReader(file)
//开始循环的读取文件的内容
for {
str, err := reader.ReadString('\n')
//为了兼容中文字符, 可以将 str 转成 []rune
strSlice := []rune(str)
//遍历 str ,进行统计
for _, v := range strSlice {
switch { // 把switch当做一个if分支使用
case v >= 'a' && v <= 'z':
fallthrough //穿透
case v >= 'A' && v <= 'Z':
count.ChCount++
case v == ' ' || v == '\t':
count.SpaceCount++
case v >= '0' && v <= '9':
count.NumCount++
default:
count.OtherCount++
}
}
if err == io.EOF { //读到文件末尾就退出
break
}
}
//输出统计的结果看看是否正确
fmt.Printf("字符的个数为=%v 数字的个数为=%v 空格的个数为=%v 其它字符个数=%v",
count.ChCount, count.NumCount, count.SpaceCount, count.OtherCount)
}
需要注意几点:
1、读到文件末尾就退出死循环。
2、把switch当做一个
if...else if...
分支使用。