一、文件读写 1.1.读文件 1.1.1. os.ReadFile 1 2 3 4 5 6 7 func ReadByOSReadFile () { dat, err := os.ReadFile("./main.go" ) check(err) fmt.Print(string (dat)) }
os.ReadFile会把所有文件的所有内容加载到内存,对于简单的小文件可以直接方便地使用
其内部实现就是循环调用file.Read方法将文件内容写入[]byte
,直到结束
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 func ReadFile (name string ) ([]byte , error ) { f, err := Open(name) if err != nil { return nil , err } defer f.Close() var size int if info, err := f.Stat(); err == nil { size64 := info.Size() if int64 (int (size64)) == size64 { size = int (size64) } } size++ if size < 512 { size = 512 } data := make ([]byte , 0 , size) for { if len (data) >= cap (data) { d := append (data[:cap (data)], 0 ) data = d[:len (data)] } n, err := f.Read(data[len (data):cap (data)]) data = data[:len (data)+n] if err != nil { if err == io.EOF { err = nil } return data, err } } }
1.1.2. file.Read
当然,我们也可以自己通过file.Read去实现完整地读,具体实现参考os.ReadFile。
自己实现就可以实现一些定制需求,例如,需要从文件的某个位置开始读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 func check (e error ) { if e != nil { panic (e) } }func ReadBySeek () { f, err := os.Open("./main.go" ) check(err) o2, err := f.Seek(8 , 0 ) check(err) b2 := make ([]byte , 4 ) n2, err := f.Read(b2) check(err) fmt.Printf("%d bytes @ %d: " , n2, o2) fmt.Printf("%v\n" , string (b2[:n2])) }
1.1.3. bufio.NewReader bufio.NewReader通过缓存去读,对于需要读许多小文件的效率比较高。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 func ReadByBufio () { f, err := os.Open("./main.go" ) check(err) defer f.Close() reader := bufio.NewReader(f) for { line, err := reader.ReadString('\n' ) if err == io.EOF { if len (line) != 0 { fmt.Println(line) } break } check(err) fmt.Print(line) } }
1.2.写文件 1.2.1. os.OpenFile os.OpenFile()函数能够以指定模式打开文件,从而实现文件写入。
1 func OpenFile (name string , flag int , perm FileMode) (*File, error ) {}
flag常用的几个位如下:
os.O_WRONLY
os.O_CREATE(文件如果不存在就创建)
os.O_RDONLY
os.O_RDWR(读写)
os.TRUNC(清空文件)
os.O_APPEND(追加)1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 func WriteByOpenFile () { f, err := os.OpenFile("tmp.txt" , os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644 ) check(err) defer f.Close() f.Write([]byte ("f.Write \n" )) f.WriteString("f.WriteString" ) writer := bufio.NewWriter(f) for i := 0 ; i < 3 ; i++ { writer.WriteString("bufio.NewWriter\n" ) } writer.Flush() }
1.2.2. os.WriteFIle os.WriteFile内部实现和我们上面写的差不多,OpenFile然后Write
1 2 3 4 5 6 7 8 func WriteByOSWriteFile () { err := os.WriteFile("tmp.txt" , []byte ("Write by os.WriteFile\n" ), 0644 ) check(err) }
二、josn文件读写 2.1.读json文件 读json文件主要就是用json.Unmarshal
方法,通常会读到一个map或者对应的结构体中
1 2 3 4 5 6 7 8 9 func ReadJsonFileToMap (filename string ) { jsonFile, err := os.Open(filename) check(err) defer jsonFile.Close() byteValue, _ := ioutil.ReadAll(jsonFile) var result map [string ]interface {} json.Unmarshal([]byte (byteValue), &result) fmt.Println(result["users" ]) }
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 type Social struct { Facebook string `json:"facebook"` Twitter string `json:"twitter"` }type User struct { Name string `json:"name"` Type string `json:"type"` Age int `json:"Age"` Social Social `json:"social"` }type Users struct { Users []User `json:"users"` }func ReadJsonFileToStruct (filename string ) { jsonFile, err := os.Open(filename) check(err) defer jsonFile.Close() byteValue, _ := ioutil.ReadAll(jsonFile) var users Users json.Unmarshal(byteValue, &users) for i := 0 ; i < len (users.Users); i++ { fmt.Println("User Type: " + users.Users[i].Type) fmt.Println("User Age: " + strconv.Itoa(users.Users[i].Age)) fmt.Println("User Name: " + users.Users[i].Name) fmt.Println("Facebook Url: " + users.Users[i].Social.Facebook) } }
users.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 { "users" : [ { "name" : "Alice" , "type" : "Reader" , "age" : 25 , "social" : { "facebook" : "https://facebook.com" , "twitter" : "https://twitter.com" } } , { "name" : "Bob" , "type" : "Author" , "age" : 28 , "social" : { "facebook" : "https://facebook.com" , "twitter" : "https://twitter.com" } } ] }
2.2.写json文件 写json文件就是Marshal后Write
1 2 3 4 func DumpJson (users *Users) { f, _ := json.MarshalIndent(&users, "" , "\t" ) ioutil.WriteFile("users_dump.json" , f, 0644 ) }
三、yaml文件读写 yaml文件的读写和json类似,都是通过Marshal和UnMarshal
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 import ( "gopkg.in/yaml.v3" "io/ioutil" )type Conf struct { Username string `yaml:"Username"` Password string `yaml:"Password"` }func ReadYaml (string filename) { buf, err := ioutil.ReadFile(filename) check(err) var conf Config yaml.Unmarshal(buf, &conf) }func WriteYaml () { conf := Conf{"test" , "test" ,} data, _ := yaml.Marshal(&conf) fmt.Printf("%v\n" , string (data)) ioutil.WriteFile("config.yaml" , data, 0644 ) }
Refs