Golang读文件 | 青训营

135 阅读2分钟

方法一:使用os.ReadFile

	f, err := os.ReadFile("/Users/litxzo/Desktop/0_1682149622.jpeg")
	if err != nil {
		fmt.Println(err.Error())
	}
	fmt.Println(string(f))

此方法直接返回一个byte数组。

  • 注意:在1.6版本后弃用了ioutil.ReadFile,改用os.ReadFile

方法二:先打开文件再ReadAll

	f, err := os.Open("/Users/litxzo/Desktop/0_1682149622.jpeg")
	if err != nil {
		fmt.Println(err.Error())
	}
	fd, _ := io.ReadAll(f)
	defer f.Close()
	fmt.Printf("%s", fd)
  • 注意ReadAll方法本来在ioutil包中,1.6版本后改到io包中。

方法三:将文件读到reader

先打开文件,再将文件读到reader中,再从reader读到buf中,最后拼到byte数组里。

	f, err := os.Open("/Users/litxzo/Desktop/0_1682149622.jpeg")
	if err != nil {
		fmt.Println(err.Error())
	}
	defer f.Close()
	r := bufio.NewReader(f)
	buf := make([]byte, 1024)
	var chunk []byte
	for {
		_, err := r.Read(buf)
		fmt.Println(buf)
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Println(err.Error())
		}
		chunk = append(chunk, buf...)
	}

	fmt.Println(string(chunk))

方法四:打开文件后read

	f, err := os.Open("/Users/litxzo/Desktop/0_1682149622.jpeg")
	if err != nil {
		fmt.Println(err.Error())
	}
	defer f.Close()
	buf := make([]byte, 1024)
	var chunk []byte
	for {
		_, err := f.Read(buf)
		fmt.Println(buf)
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Println(err.Error())
		}
		chunk = append(chunk, buf...)
	}

	fmt.Println(string(chunk))

小结

我们打开os.ReadFile的源码:

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 a file claims a small size, read at least 512 bytes.
	// In particular, files in Linux's /proc claim size 0 but
	// then do not work right if read in small pieces,
	// so an initial read of 1 byte would not work correctly.
	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
		}
	}
}

他首先打开了文件,接着用f.Stat方法获取了文件的信息,这里Stat返回描述文件的FileInfo结构。再通过返回的info.Size获得文件的长度,再另size++来多存放一个EOF。然后创建一个容量为size的data。用来存放读取的数据。

在循环读取时,这里还考虑了超出容量的异常情况。

本质上ReadFile也是打开文件并直接read的方法。