读取文件是一个经常用到的功能,比如从文件目录中读取一张照片,读取一个txt文件,word,excel等等,今天我们就学习一下go是如何读取文件的?
本节你将学到的内容如下
- 使用绝对文件路径
- 使用命令行标记来传递文件路径
- 将文件绑定在二进制文件中
- 分块读取文件
- 逐行读取文件
使用绝对文件路径
我们现在项目中创建一个文件 log.txt
package main
import (
"fmt"
"io/ioutil"
)
func main() {
data, err := ioutil.ReadFile("log.txt")
if err != nil {
fmt.Println("读取失败了", err)
return
}
fmt.Println("读取内容:", string(data))
}
我看发现这个文件找不到,为什么?
go 是编译类型的语言,编译后的程序目录和log已经不再同一个目录下面,所以代码在当前目录是找不到文件的
那么怎么才能访问到这个文件呢?
使用绝对路径,代码如下
package main
import (
"fmt"
"io/ioutil"
)
func main() {
data, err := ioutil.ReadFile("/Users/xujie/go/src/awesomeProject/main/log.txt")
if err != nil {
fmt.Println("读取失败了", err)
return
}
fmt.Println("读取内容:", string(data))
}
我们已经读取到log.txt 文件里的内容了
使用命令行标记来传递文件路径
flag 包,我们可以从输入的命令行获取到文件路径,接着读取文件内容。
首先我们来看看 flag 包是如何工作的。flag 包有一个名为 String 的函数。该函数接收三个参数。第一个参数是标记名,第二个是默认值,第三个是标记的简短描述。
下面看代码如何实现
package main
import (
"fmt"
"io/ioutil"
"flag"
)
func main() {
fptr := flag.String("fpath","log.txt","这个是读取文件的命令")
flag.Parse()
fmt.Println(*fptr)
data, err := ioutil.ReadFile(*fptr)
if err != nil {
fmt.Println("读取失败了", err)
return
}
fmt.Println("读取内容:", string(data))
}
这种方法是使用命令传参的方式执行文件
将文件绑定在二进制文件中
先安装一个第三方包
go get -u github.com/gobuffalo/packr
package main
import (
"fmt"
"github.com/gobuffalo/packr"
)
func main() {
box := packr.NewBox("") // 相对当前go文件的目录
data := box.String("log.txt")
fmt.Println("读取内容:", data)
}
三种读取文件的方式已经讲完了,但是有没有发现,我们通过上面的方式读取的都是整个文件,那么怎么分块读取文件呢?
分块读取文件
package main
import (
"os"
"bufio"
"fmt"
)
func main() {
f ,err:= os.Open("/Users/xujie/go/src/awesomeProject/main/log.txt")
defer func() {
if err = f.Close(); err != nil {
fmt.Print(err)
}
}()
if(err != nil){
fmt.Print(err)
return
}
// 1.创建一个读文件
r := bufio.NewReader(f)
// 2.创建三个字节的缓冲区 一个汉字对应三个字节
b := make([]byte,3)
for {
// 3.按三个字节读取文件
n,err := r.Read(b)
if err != nil {
break;
}
fmt.Println(n)
fmt.Println(string(b))
}
}
读取文件的步骤
1 .打开文件
2.创建读取文件结构体
3.创建读取缓冲区
4.读取文件
5.关闭文件
逐行读取文件
package main
import (
"os"
"bufio"
"fmt"
"qiniupkg.com/x/log.v7"
)
func main() {
f ,err:= os.Open("/Users/xujie/go/src/awesomeProject/main/log.txt")
defer func() {
if err = f.Close(); err != nil {
fmt.Print(err)
}
}()
if(err != nil){
fmt.Print(err)
return
}
// 1.创建一个读文件
s := bufio.NewScanner(f)
i:=0
// 2.
for s.Scan() {
fmt.Println(i)
fmt.Println(s.Text())
i++
}
err = s.Err()
if err != nil {
log.Fatal(err)
}
}
解释一下
bufio.NewScanner()
返回的是如下的对象
type Scanner struct {
r io.Reader // The reader provided by the client.
split SplitFunc // The function to split the tokens.
maxTokenSize int // Maximum size of a token; modified by tests.
token []byte // Last token returned by split.
buf []byte // Buffer used as argument to split.
start int // First non-processed byte in buf.
end int // End of data in buf.
err error // Sticky error.
empties int // Count of successive empty tokens.
scanCalled bool // Scan has been called; buffer is in use.
done bool // Scan has finished.
}
Scan() 方法读取文件的下一行,如果可以读取,就可以使用 Text() 方法,指导读取到文件的最后一行,此时如果文件中已经是最好一行了,你任然调用Scan
你就会得到一个false值
网友评论