代码改变世界

golang-标准库文件操作

  dribs  阅读(33)  评论(0编辑  收藏  举报
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package main
 
import (
    "bufio"
    "fmt"
    "os"
    "strings"
)
 
func example1() {
    filename := "e:/test.txt" //内容为abc
    //Open是只读方式打开 实际是调用的OpenFile(name, O_RDONLY, 0)
    if f, err := os.Open(filename); err == nil {
        defer f.Close()
        fmt.Printf("%T,%[1]v\n", f)
        buffer := make([]byte, 2)
        for {
            n, err := f.Read(buffer)
            fmt.Println(n, err)
            if n == 0 {
                break //什么都没读取到,说明读到了文件的结尾EOF
            }
            ////97 98
            ////99 98 buffer 读abc 以2字节读取会多98(b),覆盖方式print
            //fmt.Println(buffer)
 
            //正常读取切出来的abc,byte强制类型转换成string
            fmt.Println(buffer[:n], string(buffer[:n]))
        }
    }
 
}
 
//带指针读取
func example2() {
    filename := "e:/test.txt" //内容为0123456789
    if f, err := os.Open(filename); err == nil {
        defer f.Close()
        buffer := make([]byte, 5)
        var n int
        //指定位置,从头向后偏移3字节开始读取长度5
        n, _ = f.ReadAt(buffer, 3)
        fmt.Println(n, f.Fd(), f.Name()) //5 384 e:/test.txt
        //[51 52 53 54 55] 5 5 34567
        fmt.Println("1:", buffer, len(buffer), cap(buffer), string(buffer[:n]))
 
        //Read不共用ReadAt的seek指针
        n, _ = f.Read(buffer)
        fmt.Println("2:", buffer, n, len(buffer), cap(buffer), string(buffer[:n]))
        n, _ = f.Read(buffer)
        fmt.Println("3:", buffer, n, len(buffer), cap(buffer), string(buffer[:n]))
        n, _ = f.Read(buffer)
        //读到结尾,如果有回车,就是13 10 两个字节\r\n
        fmt.Println("4:", buffer, n, len(buffer), cap(buffer), buffer[:n])
 
        //Seek(offset int64,whence int)的whence
        //whence=0 相对于开头,offset只能正,负报错
        //whence=1 相对于当前,offset可正可负,负指针不能超左边界
        //whence=2 相对于结尾,offset可正可负,负指针不能超左边界
        off, e := f.Seek(0, 1)
        if e == nil {
            fmt.Println(off, "------")
            buffer = make([]byte, 5)
            n, _ = f.Read(buffer)
            fmt.Println(n, buffer)
        } else {
            fmt.Println(e)
        }
    }
}
 
//带缓冲读取
func example3() {
    filename := "e:/test.txt" //内容为0123456789\nabc\nxyz
    if f, err := os.Open(filename); err == nil {
        defer f.Close()
        reader := bufio.NewReader(f) //File实现了Read方法
        //reader 可以按照字节或字符读取
        b1, err := reader.ReadBytes('5')
        fmt.Println("b1:", b1, string(b1), err) //012345 <nil>
        b2 := make([]byte, 3)
        n, err := reader.Read(b2)
        fmt.Println("b2:", n, b2, string(b2[:n]), err) //3 [54 55 56] 678 <nil>
        b3, err := reader.ReadBytes('\n')
        fmt.Println("b3:", b3, string(b3), err) //b3: [57 13 10] 9\n nil
        b4, err := reader.ReadSlice('\n')
        fmt.Println("b4:", b4, string(b4), err) // [97 98 99 13 10] abc \n nil
        line, err := reader.ReadString('\n')
        fmt.Println(line, err) //xyz EOF 意思是读到了文件末尾EOF还没有找到\n
        fmt.Println(
            strings.TrimRight(line, "\n"), //移除右边的换行符
        )
 
    }
}
 
//flag
func example4() {
    filename := "e:/test1.txt"
    flag := os.O_RDONLY //只读 写不报错但也写不进去
    //flag = os.O_WRONLY               //只写 从头写 文件必须存在
    //flag = os.O_WRONLY | os.O_CREATE //文件不存在就创建后写入,文件存在就写入从头写覆盖
    //flag = os.O_CREATE               //相当于 os.O_WRONLY | os.O_CREATE
    //flag = os.O_WRONLY | os.O_APPEND //文件末尾追加写,但是文件得存在
    //flag = os.O_APPEND               //相当于os.O_WRONLY|os.O_APPEND
    //flag = os.O_EXCL                 //不要单独使用
    //flag = os.O_EXCL | os.O_CREATE //文件存在报错。不存在创建从头写
    //flag = os.O_RDWR                 //既能读又能写。从头开始,要求文件存在
 
    f, err := os.OpenFile(filename, flag, 0o640)
    if err == nil {
        defer f.Close()
        fmt.Println(f)
        f.WriteString("abcd")
        f.WriteString("efg")
    } else {
        fmt.Println(err, "!!!")
    }
}
 
//带缓冲区的读写
func example5() {
    filename := "e:/test2.txt"
    flag := os.O_RDWR | os.O_CREATE | os.O_TRUNC
    if f, err := os.OpenFile(filename, flag, os.ModePerm); err == nil {
        defer f.Close()
        r := bufio.NewReader(f)
        w := bufio.NewWriter(f)
        w.WriteString("0123456789\n")
        w.WriteString("abcd\n")
        w.Flush() //写入
 
        f.Seek(0, 0) //底层共用同一个f,指针已经指到了EOF,00拉回到开始
        fmt.Println(r.ReadString('\n'))
        //f.Seek(0, 0) //这个seek在这里其实是没用的,内部有自己的记录,如果加了这个seek,读到结尾在读就又从头开始读了,文件读写中不要乱动指针
        fmt.Println(r.ReadString('\n'))
        //fmt.Println(r.ReadString('\n'))    //又循环去读了 配合 上面注释的f.seek
    } else {
        fmt.Println(err, "!!")
    }
}
 
func main() {
    //example1()
    //example2()
    //example3()
    //example4()
    example5()
 
}

  

相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示