读文件

    我们先来看看一个简单的例子:

    运行程序可以打印整个 文件内容,如果我们将 ./main.go 修改为 ./main.go1,程序将出现 no such file or directory 的错误,所以在文件读取的时候一定要注意检查 err。

    1. package main
    2. import (
    3. "fmt"
    4. "os"
    5. )
    6. func main() {
    7. f, _ := os.Open("./main.go")
    8. defer f.Close()
    9. buf := make([]byte, 16)
    10. f.Read(buf)
    11. fmt.Println(string(buf))
    12. }

    运行程序会输出 main.go 的前 16 个字节内容,具体为:

    1. package main
    2. im

    有些时候我们想在一个文件特定地方读取特定长度的内容,那我们有什么方法可以使用呢?

    1. package main
    2. import (
    3. "fmt"
    4. "os"
    5. )
    6. func main() {
    7. f, _ := os.Open("./main.go")
    8. defer f.Close()
    9. b1 := make([]byte, 2)
    10. f.Seek(5, 0)
    11. f.Read(b1)
    12. fmt.Println(string(b1))
    13. }

    运行代码输出结果为:

    第二种:使用 f.ReadAt

    1. package main
    2. import (
    3. "fmt"
    4. "os"
    5. )
    6. func main() {
    7. f, _ := os.Open("./main.go")
    8. b1 := make([]byte, 2)
    9. f.ReadAt(b1, 5)
    10. fmt.Println(string(b1))
    11. }

    运行结果同样为:

    1. ge

    但注意:

    1. package main
    2. import (
    3. "fmt"
    4. "os"
    5. "time"
    6. )
    7. func main() {
    8. f, _ := os.Open("./main.go")
    9. defer f.Close()
    10. for i := 0; i < 5; i++ {
    11. go func() {
    12. b1 := make([]byte, 2)
    13. f.Seek(5, 0)
    14. f.Read(b1)
    15. fmt.Println(string(b1))
    16. f.Seek(2, 0)
    17. f.Read(b1)
    18. fmt.Println(string(b1))
    19. }()
    20. }
    21. time.Sleep(time.Second)
    22. }

    输出结果为:

    第二种 f.ReadAt 是并发安全的,例如:

    1. package main
    2. import (
    3. "fmt"
    4. "os"
    5. "time"
    6. )
    7. func main() {
    8. f, _ := os.Open("./main.go")
    9. defer f.Close()
    10. for i := 0; i < 5; i++ {
    11. go func() {
    12. f.ReadAt(b1, 5)
    13. f.ReadAt(b1, 2)
    14. fmt.Println(string(b1))
    15. }()
    16. }
    17. time.Sleep(time.Second)
    18. }

    输出结果为:

    1. ge
    2. ge
    3. ck
    4. ck
    5. ge
    6. ge
    7. ck
    8. ck
    9. ge
    10. ck

    实战项目一: 如何使用 buf 实现 ioutil.ReadFile 类似效果:

    1. package main
    2. import (
    3. "fmt"
    4. "io"
    5. "os"
    6. )
    7. func main() {
    8. f, _ := os.Open("./main.go")
    9. defer f.Close()
    10. content := make([]byte, 0)
    11. buf := make([]byte, 16)
    12. for {
    13. n, err := f.Read(buf)
    14. if err == io.EOF {
    15. break
    16. }
    17. if n == 16 {
    18. content = append(content, buf...)
    19. } else {
    20. content = append(content, buf[0:n]...)
    21. }
    22. }
    23. fmt.Println(string(content))

    运行结果为: