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:

  1. 打开文件:os包的 os.Open 函数。
  2. 关闭文件:os包中 File 结构体的 Close() 方法。
  3. 创建缓冲:bufio 包的 NewReader 函数。
  4. 读取文件: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...分支使用。

results matching ""

    No results matching ""