006-统计(三)
想吐槽了吗?是不是和统计杠上了啊?不是不是,这一节我们要学习一个新的包,以及另一个新的函数。先来说说要干啥。
之前我们从命令行接收文件名后,把文件打开后,直接丢给了 stat 函数去处理,这种方式是以流式来处理文件内容的。其实我们还有一种方法,我们可以一次性将文件内容全部读出来,然后再将读出来的数据按 \n
进行分割。
在 linux 系统接口中,提供了 c 语言接口 open
, read
函数可以帮我们做到,在 go 中,os 包里也提供了 os.Open
, os.Read
这些函数,也可以做到。如果真的使用这些函数,有些费劲,因为不管是 c 语言接口还是 go 语言接口,这两个 read 函数都不能保证一次性将文件内容全部读完。
所以,go 语言又提供了另一个非常好用的包 ioutil
包给我们使用。
图1 ioutil 包
可以看到 ioutil
包提供了一些比较实用的函数,其中有一个是我们想要的,即 ReadFile
函数。我们单独看看此函数的文档。
图2 ReadFile 函数
这份文档非常给力,还提供了一个示例给我们。
ReadFile
函数返回一个[]byte
,它非常像数组,实际上它是一个 byte
类型的 slice
. 没错你又再一次见到了 slice
类型。回忆一下,前面学过的 slice
类型的对象是啥?os.Args
, 它是一个 string
类型的 slice
. 不要着急,slice 类型后面一定会非常细致的讲解,在这里,『姑且』认为它就是个数组好了。
package main3. 分析
import (
"bufio"
"fmt"
"io/ioutil"
"os"
"strings"
)
func main() {
counts := make(map[string]int)
files := os.Args[1:]
if len(files) == 0 {
stat(os.Stdin, counts)
} else {
for _, file := range files {
// 注意了,在使用 ioutil 包的时候,不需要写出完整的包声明路径 io/ioutil,
// 只要写最后一部分就行了
data, err := ioutil.ReadFile(file) // 读取文件内容
if err != nil {
fmt.Fprintf(os.Stderr, "ReadFile:%v\n", err)
continue
}
// string(data) 表示把 []byte 转换成 string 类型的字符串
// strings 包提供了 Split 函数,将字符串进行分割
for _, line := range strings.Split(string(data), "\n") {
counts[line]++
}
}
}
print(counts)
}
func print(counts map[string]int) {
for key, value := range counts {
if value > 1 {
fmt.Printf("%3d %s\n", value, key)
}
}
}
func stat(f *os.File, counts map[string]int) {
inputScanner := bufio.NewScanner(f)
for
关于 ioutil.ReadFile
函数上面已经介绍过了,但是上面的程序又出现了 srings
包啊,Split
函数啊,string(data)
这些玩意儿,这些东西其实和其它语言都是类似的。
关于 string(data)
还需要提一嘴,它表示将 []byte
类型转换成 string
类型。非常像 c 语言的类型转换,但是也有点像 C++
的构造函数,好了,我们就不要猜了,好戏都在后面。
练习:
查阅一下strings
包里都有哪些函数。使用ioutil.ReadFile
函数读取文件内容,并输出到屏幕。
版权声明
本文仅代表作者观点,不代表博信信息网立场。