Go语言读取文件

在Go语言中,读取文件主要有以下几种包可用:

  • os:顾名思义,os是操作系统系统相关的包,封装了文件和目录相关的操作;
  • ioutil:io包的工具包,通过封装os的文件操作,提供上层文件读写的方法。随着版本的迭代,大部分方法即将遗弃;
  • bufio:带有缓冲区的io包;

1 os包的使用

操作文件的相关方法都在$GOROOT/src/os/file.go文件中,主要函数主要如下:

  1. OpenFile(): 较底层的一个打开文件的方式,可以灵活配置你打开的文件,比如Create()方法就是调该方法实现文件的新建;
  2. Open(): 以只读的方式打开一个文件;
  3. ReadFile(): 调Open()方法打开文件,循环读取文件内容,返回值是字节数组;
  4. WriteFile(): 向文件写入内容,如果文件不存在,则创建新文件;
  5. Create(): 新建文件;
  6. Rename(): 文件重命名。

1.1 OpenFile()方法

OpenFile()的方法源码如下:

func OpenFile(name string, flag int, perm FileMode) (*File, error) {
	testlog.Open(name)
	// 调用系统调用创建一个File对象
	f, err := openFileNolog(name, flag, perm)
	if err != nil {
		return nil, err
	}
	f.appendMode = flag&O_APPEND != 0

	return f, nil
}

其中,

  • name:是文件的路径名称
  • flag:是以什么形式打开文件,常用的O_RDONLY表示只读,O_WRONLY表示只写,O_RDWR表示读写等
  • perm:是文件的格式和权限配置,比如,0777配置当前用户、用户组和其他用户都可以执行文件

使用OpenFile()方法打开一个不存在的文件,perm配置为0777,flag配置为os.O_WRONLY|os.O_CREATE

package main

import (
	"os"
)

func main() {
	f, err := os.OpenFile("test.txt", os.O_WRONLY|os.O_CREATE, 0777)
	if err != nil {
		panic(err)
	}
	defer f.Close()
	if _, err = f.WriteString("hello world"); err != nil {
		panic(err)
	}
}

可以看到创建的文件有执行权限
在这里插入图片描述
文件内容为:

hello world

2.2 Open()方法

Open()方法底层是以可读的参数调用OpenFile()实现的:

func Open(name string) (*File, error) {
	return OpenFile(name, O_RDONLY, 0)
}

因为是只读的,所以可以使用Open()方法打开一个文件,来读取文件内容

package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	f, err := os.Open("test.txt")
	if err != nil {
		panic(err)
	}
	defer f.Close()
	Content := []byte{}
	for {
		data := make([]byte, 10)
		n, err := f.Read(data)
		if err != nil {
			if err == io.EOF {
				break
			}
			panic(err)
		}
		Content = append(Content, data[:n]...)
		fmt.Println(string(data[:n]))
	}
}

2.3 ReadFile()方法

在使用Open()方法尝试去读取文件内容时,是需要自己来通过Reade()接口循环从文件中读取字节的。如果只是想简单地读取文件的所有内容,可以使用封装后的ReadFile()方法可以更简单的实现

package main

import (
	"fmt"
	"os"
)

func main() {
	Content, err := os.ReadFile("test.txt")
	if err != nil {
		panic(err)
	}
	fmt.Println(string(Content))
}

打开ReadFile()方法的源码,能看到底层调用Open()方法,os包帮我们完成了循环读取文件内容的代码(比上面例子的实现效率更高):

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设置为字节数+1的长度,下面直接修改每个元素
	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
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值