main.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. )
  8. // appendLine 以追加方式写入一行,写完后关闭文件。
  9. func appendLine(path, text string) error {
  10. // | 是按位或:把多个打开标志组合起来。
  11. file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600)
  12. if err != nil {
  13. return err
  14. }
  15. _, writeErr := file.WriteString(text + "\n")
  16. closeErr := file.Close() // 即使写入失败,也必须尝试关闭。
  17. if writeErr != nil {
  18. return writeErr
  19. }
  20. return closeErr
  21. }
  22. // readLines 使用 Scanner 逐行读取,并演示 defer 关闭只读文件。
  23. func readLines(path string) ([]string, error) {
  24. file, err := os.Open(path)
  25. if err != nil {
  26. return nil, err
  27. }
  28. // 本例只读文件,不依赖 Close 完成写入,因此简化为忽略关闭错误。
  29. defer file.Close()
  30. var lines []string
  31. scanner := bufio.NewScanner(file)
  32. for scanner.Scan() {
  33. lines = append(lines, scanner.Text())
  34. }
  35. // Scan 返回 false,既可能是正常结束,也可能是读取失败。
  36. if err := scanner.Err(); err != nil {
  37. return nil, err
  38. }
  39. return lines, nil
  40. }
  41. func run() error {
  42. // 1. 每次创建独立临时目录,不覆盖已有文件。
  43. // 示例保留目录供你查看,不执行自动删除。
  44. directory, err := os.MkdirTemp("", "go-lesson17-")
  45. if err != nil {
  46. return err
  47. }
  48. fmt.Println("示例目录(运行后保留):", directory)
  49. // 2. Join 按当前系统规则拼接路径,避免手工拼反斜杠。
  50. path := filepath.Join(directory, "notes.txt")
  51. fmt.Printf("文件名:%s,扩展名:%s\n", filepath.Base(path), filepath.Ext(path))
  52. // 3. WriteFile 写入全部内容;已有文件会被截断并覆盖,务必确认路径。
  53. content := "第17课:文件读写\n复习 defer\n"
  54. if err := os.WriteFile(path, []byte(content), 0600); err != nil {
  55. return err
  56. }
  57. // 4. ReadFile 返回 []byte,转成 string 后按文本显示。
  58. data, err := os.ReadFile(path)
  59. if err != nil {
  60. return err
  61. }
  62. fmt.Println("=== 整体读取 ===")
  63. fmt.Print(string(data))
  64. // 5. 追加不会清空已有内容。
  65. if err := appendLine(path, "学习逐行读取"); err != nil {
  66. return err
  67. }
  68. lines, err := readLines(path)
  69. if err != nil {
  70. return err
  71. }
  72. fmt.Println("=== 追加后逐行读取 ===")
  73. for index, line := range lines {
  74. fmt.Printf("第 %d 行:%s\n", index+1, line)
  75. }
  76. // 6. Stat 获取信息。Size 是字节数,不是中文字符数。
  77. info, err := os.Stat(path)
  78. if err != nil {
  79. return err
  80. }
  81. fmt.Printf("文件名:%s,是否目录:%t,行数:%d\n", info.Name(), info.IsDir(), len(lines))
  82. return nil
  83. }
  84. func main() {
  85. if err := run(); err != nil {
  86. fmt.Fprintln(os.Stderr, "文件操作失败:", err)
  87. // run 已返回,其内部的 defer 已执行;这里才退出进程。
  88. os.Exit(1)
  89. }
  90. }