got you,goto指令使用方法

  

     

  

  欢迎来到Golang 系列教程.的第35章   

  

  读取文件是所有编程语言中最常见的操作之一。在本教程中,我们将学习如何使用Go来读取文件。   

  

  本教程分为以下几个部分。   

  

  使用绝对文件路径将整个文件读入内存,使用命令行标记传递文件路径,将文件绑定在二进制文件中,分块读取文件,逐行读取文件

将整个文件读取到内存

  

  

  ,将整个文件读入内存是最基本的文件操作之一。这需要使用ioutil包中的ReadFile函数。   

  

  我们来读取Go程序所在目录下的一个文件。我已经在GOPATH中创建了一个文件夹(音译:原文是GOROOT,应该是笔误)。在这个文件夹中,有一个文本文件test.txt,我们将使用Go程序filehandling.go来读取它。Test.txt包含文本“hello world . welcome to file handling in go”。我的文件夹结构如下:   

  

  Src文件处理file handling.gotest.txt接下来,我们来看看代码。   

  

     

  

  由于您不能在操场上读取文件,请在您的本地环境中运行此程序。   

  

  在上面程序的第9行,程序将读取文件并返回一个字节切片,这个片将保存在数据中。在第14行,我们将数据转换成字符串来显示文件的内容。   

  

  请在test.txt所在的位置运行该程序。   

  

  例如,对于linux/mac,如果test.txt位于/home/naveen/go/src/filehandling,您可以使用以下步骤运行该程序。   

  

  $ CD/home/nave en/go/src/file handling/$ go安装file handling $ workspace path/bin/file handling对于windows,如果test.txt位于C:\Users\naveen.r\go\src\filehandling,请使用以下步骤。   

  

  c : \ users \ Naven . r \ go \ src \ file handling go安装文件处理工作区路径\ bin \ file handling.exe程序将输出:   

  

  文件: hello world的内容。欢迎使用go中的文件处理。如果您在另一个位置(如/home/userdirectory)运行该程序,将会显示以下错误。   

  

  文件读取错误打开test.txt:系统找不到指定的文件。   

  

  这是因为Go是一种编译语言。Go install基于源代码创建一个二进制文件。二进制文件独立于源代码,可以在任何地方运行。因为在二进制文件运行的位置找不到test.txt,所以程序将报告一个错误,表明找不到指定的文件。   

  

  有三种方法可以解决这个问题。   

  

  使用绝对文件路径,使用命令行标记传递文件路径,在二进制文件中绑定文件,下面我们依次介绍。   

  

  

1. 使用绝对文件路径

  

  

  要解决问题,最简单的方法就是传入绝对文件路径。我已经修改了程序,把路径改成了绝对路径。   

  

     

  

  现在,您可以在任何地方运行该程序,并打印出test.txt的内容   

  

  例如,它可以在我的主目录中运行。   

  

  $ cd $ home $ go安装文件处理$ workspace path/bin/file处理这个程序打印出test.txt的内容   

  

  看起来这是一个简单的方法,但它的缺点是:文件必须放在程序指定的路径下,否则会出错。   

  

  

2. 使用命令行标记来传递文件路径

  

  

  另一种解决方案是使用命令行标记来传递文件路径。使用   

ng>flag 包,我们可以从输入的命令行获取到文件路径,接着读取文件内容。

  

首先我们来看看 flag 包是如何工作的。flag 包有一个名为 String函数。该函数接收三个参数。第一个参数是标记名,第二个是默认值,第三个是标记的简短描述。

  

让我们来编写程序,从命令行读取文件名。将 filehandling.go 的内容替换如下:

  

  

在上述程序中第 8 行,通过 String 函数,创建了一个字符串标记,名称是 fpath,默认值是 test.txt,描述为 file path to read from。这个函数返回存储 flag 值的字符串变量的地址。

  

在程序访问 flag 之前,必须先调用 flag.Parse()。

  

在第 10 行,程序会打印出 flag 值。

  

使用下面命令运行程序。

  

wrkspacepath/bin/filehandling -fpath=/path-of-file/test.txt我们传入 /path-of-file/test.txt,赋值给了 fpath 标记。

  

该程序输出:

  

value of fpath is /path-of-file/test.txt

  

这是因为 fpath 的默认值是 test.txt。

  

现在我们知道如何从命令行读取文件路径了,让我们继续完成我们的文件读取程序。

  

  

在上述程序里,命令行传入文件路径,程序读取了该文件的内容。使用下面命令运行该程序。

  

wrkspacepath/bin/filehandling -fpath=/path-of-file/test.txt请将 /path-of-file/ 替换为 test.txt 的真实路径。该程序将打印:

  

Contents of file: Hello World. Welcome to file handling in Go.

3. 将文件绑定在二进制文件中

虽然从命令行获取文件路径的方法很好,但还有一种更好的解决方法。如果我们能够将文本文件捆绑在二进制文件,岂不是很棒?这就是我们下面要做的事情。

  

有很多可以帮助我们实现。我们会使用 packr,因为它很简单,并且我在项目中使用它时,没有出现任何问题。

  

第一步就是安装 packr 包。

  

在命令提示符中输入下面命令,安装 packr 包。

  

go get -u github.com/gobuffalo/packr/...

  

packr 会把静态文件(例如 .txt 文件)转换为 .go 文件,接下来,.go 文件会直接嵌入到二进制文件中。packer 非常智能,在开发过程中,可以从磁盘而非二进制文件中获取静态文件。在开发过程中,当仅仅静态文件变化时,可以不必重新编译。

  

我们通过程序来更好地理解它。用以下内容来替换 handling.go 文件。

  

  

在上面程序的第 10 行,我们创建了一个新盒子(New Box)。盒子表示一个文件夹,其内容会嵌入到二进制中。在这里,我指定了 filehandling 文件夹,其内容包含 test.txt。在下一行,我们读取了文件内容,并打印出来。

  

在开发阶段时,我们可以使用 go install 命令来运行程序。程序可以正常运行。packr 非常智能,在开发阶段可以从磁盘加载文件。

  

使用下面命令来运行程序。

  

go install filehandlingworkspacepath/bin/filehandling该命令可以在其他位置运行。packr 很聪明,可以获取传递给 NewBox 命令的目录的绝对路径。

  

该程序会输出:

  

Contents of file: Hello World. Welcome to file handling in Go.你可以试着改变 test.txt 的内容,然后再运行 filehandling。可以看到,无需再次编译,程序打印出了 test.txt 的更新内容。完美!

  

现在我们来看看如何将 test.txt 打包到我们的二进制文件中。我们使用 packr 命令来实现。

  

运行下面的命令:

  

packr install -v filehandling它会打印:

  

building box ../filehandlingpacking file filehandling.gopacked file filehandling.gopacking file test.txtpacked file test.txtbuilt box ../filehandling with <"filehandling.go" "test.txt">filehandling该命令将静态文件绑定到了二进制文件中。

  

在运行上述命令之后,使用命令 workspacepath/bin/filehandling 来运行程序。程序会打印出 test.txt 的内容。于是从二进制文件中,我们读取了 test.txt 的内容。

  

如果你不知道文件到底是由二进制还是磁盘来提供,我建议你删除 test.txt,并在此运行 filehandling 命令。你将看到,程序打印出了 test.txt 的内容。太棒了:D。我们已经成功将静态文件嵌入到了二进制文件中。

  

分块读取文件

在前面的章节,我们学习了如何把整个文件读取到内存。当文件非常大时,尤其在 RAM 存储量不足的情况下,把整个文件都读入内存是没有意义的。更好的方法是分块读取文件。这可以使用 bufio 包来完成。

  

让我们来编写一个程序,以 3 个字节的块为单位读取 test.txt 文件。如下所示,替换 filehandling.go 的内容。

  

  

在上述程序的第 15 行,我们使用命令行标记传递的路径,打开文件。

  

在第 19 行,我们延迟了文件的关闭操作。

  

在上面程序的第 24 行,我们新建了一个缓冲读取器(buffered reader)。在下一行,我们创建了长度和容量为 3 的字节切片,程序会把文件的字节读取到切片中。

  

第 27 行的 Read 方法会读取 len(b) 个字节(达到 3 字节),并返回所读取的字节数。当到达文件最后时,它会返回一个 EOF 错误。程序的其他地方比较简单,不做解释。

  

如果我们使用下面命令来运行程序:

  

$ go install filehandling

  

$ wrkspacepath/bin/filehandling -fpath=/path-of-file/test.txt

  

会得到以下输出:

  

HelloWorld. Welcometofile handling in Go.Error reading file: EOF

逐行读取文件

本节我们讨论如何使用 Go 逐行读取文件。这可以使用 bufio 来实现。

  

请将 test.txt 替换为以下内容。

  

Hello World. Welcome to file handling in Go.This is the second line of the file.We have reached the end of the file.逐行读取文件涉及到以下步骤。

  

打开文件;在文件上新建一个 scanner;扫描文件并且逐行读取。将 filehandling.go 替换为以下内容。

  

  

在上述程序的第 15 行,我们用命令行标记传入的路径,打开文件。在第 24 行,我们用文件创建了一个新的 scanner。第 25 行的 Scan() 方法读取文件的下一行,如果可以读取,就可以使用 Text() 方法。

  

当 Scan 返回 false 时,除非已经到达文件末尾(此时 Err() 返回 nil),否则 Err() 就会返回扫描过程中出现的错误。

  

如果我使用下面命令来运行程序:

  

$ go install filehandling$ workspacepath/bin/filehandling -fpath=/path-of-file/test.txt程序会输出:

  

Hello World. Welcome to file handling in Go.This is the second line of the file.We have reached the end of the file.本教程到此结束。希望你能喜欢,祝你愉快。

  

历史文章:

  

「GCTT 出品」Go 系列教程――1. 介绍与安装

  

「GCTT 出品」Go 系列教程――2. Hello World

  

「GCTT 出品」Go 系列教程――3. 变量

  

「GCTT 出品」Go 系列教程――4. 类型

  

「GCTT 出品」Go 系列教程――5. 常量

  

「GCTT 出品」Go 系列教程――6. 函数(Function)

  

「GCTT 出品」Go 系列教程――7. 包

  

Go 系列教程――8. if-else 语句

  

「GCTT 出品」Go 系列教程――9. 循环

  

「GCTT 出品」Go 系列教程――10. switch 语句

  

「GCTT 出品」Go 系列教程――11. 数组和切片

  

「GCTT 出品」Go 系列教程――12. 可变参数函数

  

「GCTT 出品」Go 系列教程――13. Maps

  

「GCTT 出品」Go 系列教程――14. 字符串

  

「GCTT 出品」Go 系列教程――15. 指针

  

「GCTT 出品」Go 系列教程――16. 结构体,这一篇就够

  

「GCTT 出品」Go 系列教程――17. 超全的方法教程

  

「GCTT 出品」Go 系列教程――18. 接口(一)

  

「GCTT 出品」Go 系列教程――19. 接口(二)

  

「GCTT 出品」Go 系列教程――20. 并发入门

  

「GCTT 出品」Go 系列教程――21. Go 协程

  

「GCTT 出品」Go 系列教程――22. 信道(channel)

  

「GCTT 出品」Go 系列教程――23. 缓冲信道和工作池

  

「GCTT 出品」Go 系列教程――24. Select

  

「GCTT 出品」Go 系列教程――25. Mutex

  

「GCTT 出品」Go 系列教程――26. 结构体取代类

  

「GCTT 出品」Go 系列教程――27. 组合取代继承

  

「GCTT 出品」Go 系列教程――28. 多态

  

「GCTT 出品」Go 系列教程――29. Defer

  

「GCTT 出品」Go 系列教程――30. 错误处理

  

「GCTT 出品」Go 系列教程――31. 自定义错误

  

「GCTT 出品」Go 系列教程――32. panic 和 recover

  

「GCTT 出品」Go 系列教程――33. 函数是一等公民(头等函数)

  

「GCTT 出品」Go 系列教程――34. 反射

相关文章