• Go 文件读写


    一、文件读写

    1.1.读文件

    1.1.1. os.ReadFile
    func ReadByOSReadFile() {
    	dat, err := os.ReadFile("./main.go")
    	// ioutil.ReadFile等同于os.ReadFile
    	// dat, err := ioutil.ReadFile("./main.go")
    	check(err)
    	fmt.Print(string(dat))
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • os.ReadFile会把所有文件的所有内容加载到内存,对于简单的小文件可以直接方便地使用
    • 其内部实现就是循环调用file.Read方法将文件内容写入[]byte,直到结束
    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++ // one byte for final read at EOF
    
    	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
    • 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
    1.1.2. file.Read
    • 当然,我们也可以自己通过file.Read去实现完整地读,具体实现参考os.ReadFile。
    • 自己实现就可以实现一些定制需求,例如,需要从文件的某个位置开始读
    func check(e error) {
    	if e != nil {
    		panic(e)
    	}
    }
    
    // file.Seek(offset, whence)
    // offset:偏移量
    // whence:0:从头开始;1: 从当前位置开始;2:从结尾开始
    
    func ReadBySeek() {
    	f, err := os.Open("./main.go")
    	check(err)
    	// 将文件指针移动到 从文件头开始,偏移8位
    	// 返回偏移的位置
    	o2, err := f.Seek(8, 0)
    	check(err)
    
    	// 从当前文件指针位置开始读4个字节
    	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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    1.1.3. bufio.NewReader

    bufio.NewReader通过缓存去读,对于需要读许多小文件的效率比较高。

    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
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    1.2.写文件

    1.2.1. os.OpenFile

    os.OpenFile()函数能够以指定模式打开文件,从而实现文件写入。

    func OpenFile(name string, flag int, perm FileMode) (*File, error) {}
    
    • 1

    flag常用的几个位如下:

    • os.O_WRONLY
    • os.O_CREATE(文件如果不存在就创建)
    • os.O_RDONLY
    • os.O_RDWR(读写)
    • os.TRUNC(清空文件)
    • os.O_APPEND(追加)
    func WriteByOpenFile() {
    	// 如果文件不存在,则创建;写入时先请空文件再开始写
    	f, err := os.OpenFile("tmp.txt", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
    	check(err)
    	defer f.Close()
    	// 写入bytes
    	f.Write([]byte("f.Write \n"))
    	// 写入string
    	f.WriteString("f.WriteString")
    	
    	// 通过bufio.NewWriter写入(基于缓存)
    	writer := bufio.NewWriter(f)
    	for i := 0; i < 3; i++ {
    		writer.WriteString("bufio.NewWriter\n") // 先写入缓存
    	}
    	writer.Flush() // 注意,如果没有flush的话,即使文件关闭了也不会写入文件
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    1.2.2. os.WriteFIle

    os.WriteFile内部实现和我们上面写的差不多,OpenFile然后Write

    func WriteByOSWriteFile() {
    
    	err := os.WriteFile("tmp.txt", []byte("Write by os.WriteFile\n"), 0644)
    	
    	// ioutil.WriteFile等同于OSWriteFile
    	// err := ioutil.WriteFile("tmp.txt", []byte("Write by ioutil.WriteFile\n"), 0644)
    	check(err)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    二、josn文件读写

    2.1.读json文件

    读json文件主要就是用json.Unmarshal方法,通常会读到一个map或者对应的结构体中

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

    users.json

    {
      "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"
          }
        }
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    2.2.写json文件

    写json文件就是Marshal后Write

    func DumpJson(users *Users) {
    	f, _ := json.MarshalIndent(&users, "", "\t")
    	ioutil.WriteFile("users_dump.json", f, 0644)
    }
    
    • 1
    • 2
    • 3
    • 4

    三、yaml文件读写

    yaml文件的读写和json类似,都是通过Marshal和UnMarshal

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

    Refs

    • https://gobyexample.com/reading-files
    • https://tutorialedge.net/golang/parsing-json-with-golang/
    • https://dev.to/sagartrimukhe/generate-yaml-files-in-golang-29h1
  • 相关阅读:
    账号安全基本措施1
    解决线上OutOfMemoryError: GC overhead limit exceeded问题
    Mybatis【全面学习 一篇就够】
    【HTML】
    SlicePlane的Heading角度与Math.atan2(y,x)的对应转换关系
    opencv+tesseract完成验证码识别(识别率99.99%)
    【深度学习实验】前馈神经网络(五):自定义线性模型:前向传播、反向传播算法(封装参数)
    组合模式(Composite Pattern)
    设计模式详解(九)——桥接模式
    基于 XAF Blazor 的规则引擎编辑器 - 介绍篇
  • 原文地址:https://blog.csdn.net/qq_41832237/article/details/126415235