其他分享
首页 > 其他分享> > Go语言学习22-文件操作——开关读

Go语言学习22-文件操作——开关读

作者:互联网

0x00 文件操作

在Go语言中,任何的文件读取或者写入,都是先打开文件——注册(defer)关闭文件

然后再读写操作

0x01 基本的方式打开文件以及读文件

用到了os包中的Open函数。Open函数打开的文件,会返回两个值,一个为错误err,一个为文件类型的指针。

image-20220302193242002

读文件

使用的就是打开文件后,返回的一个文件类型的指针的Read方法。可以看到Read方法里面的参数为[]byte类型,即byte切片。

那么我指定切片长度后,初始化即可。

image-20220302180252557

当然,初始化的方式有很多种,最常用的两种就是:

var tmp = make([]byte,128)

还有一种就是:

var tmp = [128]byte		//定义一个数组
fileObj.Read(tmp[:])	//从数组中创建切片,即从数组切出所有的切片

image-20220302193500933

package main

import (
	"fmt"
	"os"
)

func main() {
	fileobj, err := os.Open("./main.go")
	if err != nil {
		fmt.Println("sorry , the file opening is wrong!", err)
		return
	}
	// fmt.Println(fileobj)
	//记得关闭文件
	defer fileobj.Close()
	//读文件
	// var tmp = make([]byte,128)
	var tmp [128]byte
	n, err := fileobj.Read(tmp[:])
	if err != nil {
		fmt.Printf("read from file failed!,err%v\n", err)
		return
	}
	fmt.Printf("读了%d个字节!\n", n)
	fmt.Println(string(tmp[:n])) //左边开头到右边为n的

}

image-20220302182114829

上面这段代码,可以看到这里并没有读完,仅仅读到了128个字节而已。那么怎么办呢?加个for循环即可。可以看到第20行添加了一个for关键词。再加一个if判断,也就是当n等于0的时候,就会结束读取文件内容,直接return跳出函数。

package main

import (
	"fmt"
	"os"
)

func main() {
	fileobj, err := os.Open("./main.go")
	if err != nil {
		fmt.Println("sorry , the file opening is wrong!", err)
		return
	}
	// fmt.Println(fileobj)
	//记得关闭文件
	defer fileobj.Close()
	//读文件
	// var tmp = make([]byte,128)
	var tmp [128]byte
	for {
		n, err := fileobj.Read(tmp[:])
		if err != nil {
			fmt.Printf("read from file failed!,err%v\n", err)
			return
		}
		fmt.Printf("读了%d个字节!\n", n)
		fmt.Println(string(tmp[:n])) //左边开头到右边为n的
		if n == 0 {
			return
		}
	}

}

虽然可以读出来,但是有一个报错。这是为什么呢?这个报错其实很简单,就是EOF而已,EOF代表的意思为:end of file!!!

image-20220302192526989

还能怎么改进呢?其实改一下n的值即可

var tmp [128]byte
	for {
		n, err := fileobj.Read(tmp[:])
		if err != nil {
			fmt.Printf("read from file failed!,err%v\n", err)
			return
		}
		fmt.Printf("读了%d个字节!\n", n)
		fmt.Println(string(tmp[:n])) //左边开头到右边为n的
		if n < 128 {			//	小于128就可以出现一个情况,因为每次都是读128个字节,一旦比128少,就说明读完了,就这么多。
			return	
		}
	}

image-20220302192900673

0x02 bufio读文件

buf——>buffer缓冲区,就是先将读取的文件放入缓冲区,然后再进行读取。

func readFromFile2() {
	//利用bufio读取文件
	//前面还是一样的,先打开文件,然后再读取内容
	fileobj, err := os.Open("./main.go")
	if err != nil {
		fmt.Println("err:", err)
		return
	}
	defer fileobj.Close()

	//创建一个用来从文件中读内容的对象
	reader := bufio.NewReader(fileobj)
	for {
        //for循环里面的内容,就是依次向下读取一行文本内容
		line, err := reader.ReadString('\n')
		if err == io.EOF {
			return
		}
		if err != nil {
			fmt.Println("err", err)
			return
		}
		fmt.Println(line)
	}

}

image-20220302200046756

但是有没有注意到,我打印出来的内容都是一行隔着一行的?是因为我用到的是fmt.Println,没输出一次换一行。

所以改成fmt.Print即可。

0x03 第三种读取文件——利用ioutil包

十分简单,看代码就会了

func readFromFile3() {
	file, err := ioutil.ReadFile("./main.go")
	if err != nil {
		fmt.Println("err:", err)
		return
	}
	fmt.Println("file:", string(file))
}

image-20220302200421522

ioutil包解析

image-20220302200658148

可以看到,其实就是封装了一个函数,前面都是我们熟悉的:先打开文件,然后注册defer关闭文件,后面才开始逐渐不一样开来。

image-20220302200837563

总结

三种读取文件的方法各自特点:

1、如果想要自定义读取多少字节,多少内容,使用第一种方法,即fileobj.Read()方法。

2、如果想要实现一行一行读取代码,就使用第二种方法。

3、如果想要一次性读完,就使用第三种即可,第三种读起来十分方便。

三种读取文件的代码总结

package main

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"os"
)

func readFromFile1() {
	fileobj, err := os.Open("./main.go")
	if err != nil {
		fmt.Println("sorry , the file opening is wrong!", err)
		return
	}
	// fmt.Println(fileobj)
	//记得关闭文件
	defer fileobj.Close()
	//读文件
	// var tmp = make([]byte,128)
	var tmp [128]byte
	for {
		n, err := fileobj.Read(tmp[:])
		if err != nil {
			fmt.Printf("read from file failed!,err%v\n", err)
			return
		}
		fmt.Printf("读了%d个字节!\n", n)
		fmt.Println(string(tmp[:n])) //左边开头到右边为n的
		if n < 128 {
			return
		}
	}
}

func readFromFile2() {
	//利用bufio读取文件
	//前面还是一样的,先打开文件,然后再读取内容
	fileobj, err := os.Open("./main.go")
	if err != nil {
		fmt.Println("err:", err)
		return
	}
	defer fileobj.Close()

	//创建一个用来从文件中读内容的对象
	reader := bufio.NewReader(fileobj)
	for {
		line, err := reader.ReadString('\n')
		if err == io.EOF {
			return
		}
		if err != nil {
			fmt.Println("err", err)
			return
		}
		fmt.Println(line)
	}

}
func readFromFile3() {
	file, err := ioutil.ReadFile("./main.go")
	if err != nil {
		fmt.Println("err:", err)
		return
	}
	fmt.Println("file:", string(file))
}
func main() {
	readFromFile1()
	readFromFile2()
	readFromFile3()
}

标签:Println,tmp,return,22,err,fmt,开关,fileobj,Go
来源: https://www.cnblogs.com/sukusec301/p/15956949.html