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")
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM