第二十六回:Go 文件处理

藏在书房的秘密(File I/O)
唐伯虎
唐伯虎: 嘘!我们要潜入华太师的书房,找到那本传说中的《唐寅诗集》。这就需要用到文件操作的功夫。
秋香
秋香: 公子小心,书房里有很多机关(错误处理)。而且看完书记得要把书合上(Close),不然书房门(文件句柄)关不上,会被太师发现的!

🔍 第一招:投石问路 (检查文件与路径)

在动手之前,先看看书在不在。用 os.Stat。另外,为了防止在不同操作系统(Windows/Linux)迷路,一定要用 filepath 包来处理路径。

import (
    "fmt"
    "os"
    "path/filepath"
)

func CheckBook() {
    // 自动处理路径分隔符 (Windows用\, Linux用/)
    path := filepath.Join("书房", "唐寅诗集.txt")
    
    // os.Stat 获取文件信息 (大小、修改时间等)
    info, err := os.Stat(path)
    
    if os.IsNotExist(err) {
        fmt.Println("书房里没有这本书...")
        return
    }
    
    fmt.Printf("找到宝书了!大小:%d 字节\n", info.Size())
}

📂 第二招:一目十行 (读取文件)

最简单的方法是一次性读完(适合小纸条)。但如果是《四书五经》那么厚的书,一次读完内存会爆掉!

1. 小抄模式 (os.ReadFile)

适合读取小文件,直接将所有内容读到内存里。

func ReadSecret() {
    // 以前叫 ioutil.ReadFile,Go 1.16 后直接用 os.ReadFile
    content, err := os.ReadFile("secret.txt")
    if err != nil {
        panic("找不到小抄!")
    }
    fmt.Println("小抄内容:", string(content))
}

2. 诵读模式 (bufio 按行读取)

适合读取大文件,一行一行地读,就像背书一样。省内存。

import (
    "bufio"
    "os"
)

func ReadBigBook() {
    // 1. 打开书本
    file, err := os.Open("四书五经.txt")
    if err != nil {
        panic(err)
    }
    // ⚠️ 关键:看完书记得合上!(defer 会在函数结束前执行)
    defer file.Close()

    // 2. 创建一个扫描仪(眼睛)
    scanner := bufio.NewScanner(file)

    // 3. 一行行看
    lineCount := 0
    for scanner.Scan() {
        line := scanner.Text() // 获取当前行的文字
        fmt.Println("正在背诵:", line)
        lineCount++
    }
    
    if err := scanner.Err(); err != nil {
        fmt.Println("背书背岔气了:", err)
    }
}

📝 第三招:挥毫泼墨 (写文件)

1. 涂鸦模式 (os.WriteFile)

直接覆盖原来的内容(慎用!会把原来的诗擦掉)。

d1 := []byte("桃花大仙种桃树,又摘桃花换酒钱")
// 0644 是文件权限:我自己能读写(6),别人只能读(4)
err := os.WriteFile("新诗.txt", d1, 0644)

2. 专业模式 (os.OpenFile)

如果你想追加内容,或者控制读写权限,需要用 os.OpenFile 配合 Flag(标志位)。

func WriteDiary() {
    // 打开日记本:追加模式 | 如果没有就创建 | 只写模式
    f, err := os.OpenFile("diary.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
    if err != nil {
        panic(err)
    }
    defer f.Close()

    if _, err = f.WriteString("\n今天秋香姐冲我笑了!开心!"); err != nil {
        panic(err)
    }
}
华夫人
华夫人: 记住,文件操作完一定要 Close!虽然 Go 的 GC 会回收内存,但它不负责关闭文件句柄。如果句柄耗尽,你的程序就瘫痪了!用 defer 是个好习惯。

🔥 第四招:毁尸灭迹 (删除文件)

看完书后,为了不留痕迹,有时需要删除文件。

err := os.Remove("秘密账本.txt")
if err != nil {
    fmt.Println("删除失败:", err)
} else {
    fmt.Println("成功销毁证据!")
}

🎯 练功房(偷看日记)

使用 os.ReadFile 快速读取 diary.txt 的内容。

package main
import (
    "os"
    "fmt"
)

func main() {
    // 填空:读取文件
    data, _ := os.____("diary.txt")
    fmt.Println(string(data))
}

任务: 函数名是什么?

答案: ReadFile

解析: os.ReadFile 是 Go 1.16 引入的便捷函数,替代了以前的 ioutil.ReadFile