go 文件操作实践[读写json xlm gob txt]
go常用操作文件有json,xml, gob 和txt,一般json,xml, gob 都是全部操作 很少修改一个部分快的内容, 所以一般采用 编码、解码实现,txt可能有追加所以相对难一点。 说说自己遇到的坑
1.验证文件或者目录是否存在
// 检查文件或目录是否存在 // 如果由 filename 指定的文件或目录存在则返回 true,否则返回 false func IsExist(filename string) bool { _, err := os.Stat(filename) return err == nil || os.IsExist(err) }
2在读取文本文件的时候
Readline读满缓冲区就返回,剩下的字节不会丢弃,留着下次读取。这样一行就拆分成了两次读取,两次读取出来的行都与预期的不符,后续的逻辑流程肯定也异常了 解决方法: 1.直接换成ReadBytes(’\ n’) 或 ReadString(’\ n’) 2.对isPrefix返回值做校验
3. os.OpenFile(filePath, os.O_RDWR|os.O_APPEND, 0666) 这个方法的flag一定要注意, 比如 设置成os.O_WRONLY|os.O_APPEND , 去读取文件, 结果是阻塞不是报错。
整个dmeo 如下:
package main import ( "bufio" "encoding/gob" "encoding/json" "encoding/xml" "fmt" "io" "os" ) type Website struct { Name string `xml:"name,attr"` Url string Course []string } var info []Website func init() { info = []Website{ {"Golang", "http://c.biancheng.net/golang/", []string{"http://c.biancheng.net/cplus/", "http://c.biancheng.net/linux_tutorial/"}}, {"Java", "http://c.biancheng.net/java/", []string{"http://c.biancheng.net/socket/", "http://c.biancheng.net/python/"}}, } /* 列举了一些常用的 flag 文件处理参数: O_RDONLY:只读模式打开文件; O_WRONLY:只写模式打开文件; O_RDWR:读写模式打开文件; O_APPEND:写操作时将数据附加到文件尾部(追加); O_CREATE:如果不存在将创建一个新文件; O_EXCL:和 O_CREATE 配合使用,文件必须不存在,否则返回一个错误; O_SYNC:当进行一系列写操作时,每次都要等待上次的 I/O 操作完成再进行; O_TRUNC:如果可能,在打开时清空文件。 */ } // 检查文件或目录是否存在 // 如果由 filename 指定的文件或目录存在则返回 true,否则返回 false func IsExist(filename string) bool { _, err := os.Stat(filename) return err == nil || os.IsExist(err) } func main() { WriteJson() ReadJson() WriteXml() ReadXML() WriteGob() ReadGob() WriteorCreatetxt() OpenAndAppendtxt() txtReadLine() } func WriteJson() { path := "./info.json" if IsExist(path) { os.Remove(path) } fileptr, err := os.Create(path) if err != nil { fmt.Printf("crete json file has error:%v\n", err) return } defer fileptr.Close() encoder := json.NewEncoder(fileptr) err = encoder.Encode(info) if err != nil { fmt.Printf("json encode hase error %v\n", err) } else { fmt.Println("json write done") } } func ReadJson() { path := "./info.json" fileptr, err := os.Open(path) if err != nil { fmt.Printf("open json file has error:%v\n", err) return } defer fileptr.Close() var tmp []Website decoder := json.NewDecoder(fileptr) err = decoder.Decode(&tmp) if err != nil { fmt.Printf("json decode has error:%v\n", err) } fmt.Println("json read done") fmt.Print(tmp) } func WriteXml() { path := "./info.xml" if IsExist(path) { os.Remove(path) } fileptr, err := os.Create(path) if err != nil { fmt.Printf("crete xml file has error:%v\n", err) return } defer fileptr.Close() encoder := xml.NewEncoder(fileptr) err = encoder.Encode(info) if err != nil { fmt.Printf("xml encode hase error %v\n", err) } else { fmt.Println("xml write done") } } func ReadXML() { path := "./info.xml" fileptr, err := os.Open(path) if err != nil { fmt.Printf("open xml file has error:%v\n", err) return } defer fileptr.Close() var tmp []Website decoder := xml.NewDecoder(fileptr) err = decoder.Decode(&tmp) if err != nil { fmt.Printf("xml decode has error:%v\n", err) } fmt.Println("xml read done") fmt.Print(tmp) } func WriteGob() { path := "./demo.gob" if IsExist(path) { os.Remove(path) } file, _ := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0777) defer file.Close() enc := gob.NewEncoder(file) if err := enc.Encode(info); err != nil { fmt.Printf("gob endcod has err:%v", err) } else { fmt.Println("gob write don") } } func ReadGob() { path := "./demo.gob" fileptr, err := os.Open(path) if err != nil { fmt.Printf("open gob file has error:%v\n", err) return } defer fileptr.Close() var tmp []Website decoder := gob.NewDecoder(fileptr) err = decoder.Decode(&tmp) if err != nil { fmt.Printf("gob decode has error:%v\n", err) } fmt.Println("gob read done") fmt.Print(tmp) } func WriteorCreatetxt() { filePath := "./info.txt" file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666) if err != nil { fmt.Printf("txt open file has err:%v", err) } defer file.Close() //写入文件时,使用带缓存的 *Writer write := bufio.NewWriter(file) for i := 0; i < 5; i++ { write.WriteString(fmt.Sprintf("hello:%d \r\n", i+1)) } //Flush将缓存的文件真正写入到文件中 write.Flush() fmt.Println("txt write done") } func OpenAndAppendtxt() { filePath := "./info.txt" file, err := os.OpenFile(filePath, os.O_RDWR|os.O_APPEND, 0666) if err != nil { fmt.Printf("txt open file has err:%v", err) } defer file.Close() //读原来文件的内容,并且显示在终端 reader := bufio.NewReader(file) for { str, err := reader.ReadString('\n') if err == io.EOF { break } fmt.Print(str) } //写入文件时,使用带缓存的 *Writer write := bufio.NewWriter(file) for i := 0; i < 5; i++ { write.WriteString(fmt.Sprintf("world %d\r\n", i+1)) } //Flush将缓存的文件真正写入到文件中 write.Flush() fmt.Println("txt append done") } /* Readline读满缓冲区就返回,剩下的字节不会丢弃,留着下次读取。 这样一行就拆分成了两次读取,两次读取出来的行都与预期的不符,后续的逻辑流程肯定也异常了 解决方法: 1.直接换成ReadBytes(’\ n’) 或 ReadString(’\ n’) 2.对isPrefix返回值做校验 */ func txtReadLine() { // 打开test.txt文件 fi, err := os.Open("./test.txt") if err != nil { fmt.Println("open file error:", err) return } defer fi.Close() // 逐行读取记录 br := bufio.NewReader(fi) var buf []byte for { line, prefix, err := br.ReadLine() if err == io.EOF { break } // 追加到自定义缓冲区内 buf = append(buf, line...) // 如果prefix为真,则代表该行还有尚未读取完的数据,跳过后续具体操作,继续读取完该行剩余内容 if prefix { continue } str := string(buf) fmt.Printf("--------------------\n") fmt.Println("len(buf) = ", len(buf)) fmt.Println("len(str) = ", len(str)) fmt.Println(str) fmt.Printf("--------------------\n\n") // 清空切片 buf = append(buf[:0], buf[len(buf):]...) } fmt.Println("txt readline done") }
windows技术爱好者
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构