Go语言读取文件的常用方式

1. 使用 os.Open(path) 函数和 Read() 方法,os.Open() 函数创建文件句柄,Read() 读取文件内容,path 为需要读取的文件路径,最好传递绝对路径这样不会出现错误,Read() 方法需要传递一个 byte 切片,所以需要声明一个 byte 切片,这里需要注意一下需要设置一下切片的长度,如果没有设置切片长度,官方文档说了最终读取的到切片的 byte 数目会可能会小于 byte 切片长度,没有声明长度最终读取的结果就是0,声明一个切片 data 来记录读取文件的结果(可以阅读官方文档的给出的例子),当读取到文件末尾的时候 Read() 方法返回的结果就是0,所以当 n = 0 的时候直接 break 即可:

package main

import (
	"fmt"
	"io"
	"log"
	"os"
	"time"
)

func main() {
	path := "C:\\Users\\Desktop\\data.txt"
	f, err := os.Open(path)
	if err != nil {
		// 打开文件失败
		log.Fatal(err)
	}
	var data []byte
	buf := make([]byte, 1024)
	t1 := time.Now()
	for {
        // 将文件中读取的byte存储到buf中
		n, err := f.Read(buf)
		if err != nil && err != io.EOF {
			log.Fatal(err)
		}
		if n == 0 {
			break
		}
        // 将读取到的结果追加到data切片中
		data = append(data, buf[:n]...)
	}
    // 将data切片转为字符串即使文件内容
    // fmt.Println(string(data))
	t2 := time.Now()
    // 计算读取文件的耗时
	fmt.Println(t2.Sub(t1))
}

2. 使用 os.Open() 函数和 bufio 包中的 NewReader() 函数,bufio 包实现了输入输出数据缓存的相关读写操作,调用 bufio 包中的 NewReader() 函数会返回一个大小为新创建的具有 4096 byte的缓冲区的 Reader 结构体指针类型(NewReader() 函数的参数为一个 io.Reader 接口,所以只要是实现了 Reader 接口的 read() 方法就可以传递到 NewReader() 函数,例如还可以传递 os.Stdin 标准输入,可以从标准输入中读取数据),Read() 方法执行一次系统调用读取 4096 byte 大小到缓冲区,此后 Read() 方法都会从缓冲区中读,普通 io 每次读写操作都会执行系统调用,必然会比使用  bufio 中的 Read() 方法慢很多,因为每次系统调用都会从用户态到内核态的切换:

package main

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"os"
	"time"
)

func main() {
	path := "C:\\Users\\Desktop\\data.txt"
	f, err := os.Open(path)
	if err != nil {
		fmt.Println("打开文件失败")
		log.Fatal(err)
	}
    // 注意buf不能够声明为没有长度的切片, 例如这样声明: var buf []byte是不可以的, 因为官方文档说了最终返回的字节数目n可能小于len(buf), 所以切片需要长度否则读取不了数据
	var buf = make([]byte, 4096)
	var data []byte
	reader := bufio.NewReader(f)
	t1 := time.Now()
	for {
		n, err := reader.Read(buf)
		if err != nil && err != io.EOF {
			log.Fatal(err)
		}
		// 文件末尾那么退出
		if n == 0 {
			break
		}
		// 将读取到的数据追加到data切片中
		data = append(data, buf[:n]...)
	}
	//fmt.Println(string(data))
	t2 := time.Now()
	fmt.Println(t2.Sub(t1))
}

3. os.Open() 函数 ioutil.ReadAll() 函数:

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"time"
)

func main() {
	t1 := time.Now()
	path := "C:\\Users\\Desktop\\data.txt"
	fi, _ := os.Open(path)
	_, err := ioutil.ReadAll(fi)
	if err != nil {
		log.Fatal(err)
	}
	t2 := time.Now()
	fmt.Println(t2.Sub(t1))
}

三种读取文件的方法中第二种和第三种方法的速度是比较快的,第一种会相对比较慢一点,我们可以使用 python 生成一个比较大的 data.txt 文件,然后使用三种读取文件的方法输出每一种方法的耗时:

if __name__ == "__main__":
    file = open("data.txt", "w")
    # 将数据写入到文件
    for i in range(1, 10 ** 6):
        s = ""
        for j in range(26):
            s += chr(97 + j)
        print(s, file=file)
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值