mirror of
https://github.com/unknwon/the-way-to-go_ZH_CN.git
synced 2025-08-12 05:11:49 +08:00
12.2
This commit is contained in:
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
## 翻译进度
|
## 翻译进度
|
||||||
|
|
||||||
12.1 [读取用户的输入](eBook/12.1.md)
|
12.2 [文件读写](eBook/12.2.md)
|
||||||
|
|
||||||
## 支持本书
|
## 支持本书
|
||||||
|
|
||||||
|
@@ -30,4 +30,4 @@ Golang 编程:245386165
|
|||||||
|
|
||||||
|更新日期 |更新内容
|
|更新日期 |更新内容
|
||||||
|----------|------------------
|
|----------|------------------
|
||||||
|2015-11-11|12.1 读取用户的输入
|
|2015-11-12|12.2 文件读写
|
||||||
|
1
TOC.md
1
TOC.md
@@ -106,3 +106,4 @@
|
|||||||
- 第三部分:Go 高级编程
|
- 第三部分:Go 高级编程
|
||||||
- 第12章:[读写数据](12.0.md)
|
- 第12章:[读写数据](12.0.md)
|
||||||
- 12.1 [读取用户的输入](12.1.md)
|
- 12.1 [读取用户的输入](12.1.md)
|
||||||
|
- 12.2 [文件读写](12.2.md)
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
在 Go 语言中,文件使用指向 `os.File` 类型的指针来表示的,也叫做文件句柄。我们在前面章节使用到过标准输入 `os.Stdin` 和标准输出 `os.Stdout`,他们的类型都是 `*os.File`。让我们来看看下面这个程序:
|
在 Go 语言中,文件使用指向 `os.File` 类型的指针来表示的,也叫做文件句柄。我们在前面章节使用到过标准输入 `os.Stdin` 和标准输出 `os.Stdout`,他们的类型都是 `*os.File`。让我们来看看下面这个程序:
|
||||||
|
|
||||||
示例 12.4 [fileinput.go](examples/chapter_12/fileinput.go):
|
示例 12.4 [fileinput.go](examples/chapter_12/fileinput.go):
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
import (
|
import (
|
||||||
@@ -35,7 +36,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
变量 `inputFile` 是 `*os.File` 类型的。该类型是一个结构,表示一个打开文件的描述符(文件句柄)。然后,使用 `os` 包里的 `Open` 函数来打开一个文件。该函数的参数是文件名,类型为 `string`。在上面的程序中,我们以只读模式打开 input.dat 文件。
|
变量 `inputFile` 是 `*os.File` 类型的。该类型是一个结构,表示一个打开文件的描述符(文件句柄)。然后,使用 `os` 包里的 `Open` 函数来打开一个文件。该函数的参数是文件名,类型为 `string`。在上面的程序中,我们以只读模式打开 `input.dat` 文件。
|
||||||
|
|
||||||
如果文件不存在或者程序没有足够的权限打开这个文件,Open函数会返回一个错误:`inputFile, inputError = os.Open("input.dat")`。如果文件打开正常,我们就使用 `defer.Close()` 语句确保在程序退出前关闭该文件。然后,我们使用 `bufio.NewReader` 来获得一个读取器变量。
|
如果文件不存在或者程序没有足够的权限打开这个文件,Open函数会返回一个错误:`inputFile, inputError = os.Open("input.dat")`。如果文件打开正常,我们就使用 `defer.Close()` 语句确保在程序退出前关闭该文件。然后,我们使用 `bufio.NewReader` 来获得一个读取器变量。
|
||||||
|
|
||||||
@@ -54,6 +55,7 @@ func main() {
|
|||||||
如果您想这么做,可以使用 `io/ioutil` 包里的 `ioutil.ReadFile()` 方法,该方法第一个返回值的类型是 `[]byte`,里面存放读取到的内容,第二个返回值是错误,如果没有错误发生,第二个返回值为 nil。请看示例 12.5。类似的,函数 `WriteFile()` 可以将 `[]byte` 的值写入文件。
|
如果您想这么做,可以使用 `io/ioutil` 包里的 `ioutil.ReadFile()` 方法,该方法第一个返回值的类型是 `[]byte`,里面存放读取到的内容,第二个返回值是错误,如果没有错误发生,第二个返回值为 nil。请看示例 12.5。类似的,函数 `WriteFile()` 可以将 `[]byte` 的值写入文件。
|
||||||
|
|
||||||
示例 12.5 [read_write_file1.go](examples/chapter_12/read_write_file1.go):
|
示例 12.5 [read_write_file1.go](examples/chapter_12/read_write_file1.go):
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
import (
|
import (
|
||||||
@@ -81,12 +83,14 @@ func main() {
|
|||||||
**2) 带缓冲的读取**
|
**2) 带缓冲的读取**
|
||||||
|
|
||||||
在很多情况下,文件的内容是不按行划分的,或者干脆就是一个二进制文件。在这种情况下,`ReadString()`就无法使用了,我们可以使用 `bufio.Reader` 的 `Read()`,它只接收一个参数:
|
在很多情况下,文件的内容是不按行划分的,或者干脆就是一个二进制文件。在这种情况下,`ReadString()`就无法使用了,我们可以使用 `bufio.Reader` 的 `Read()`,它只接收一个参数:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
buf := make([]byte, 1024)
|
buf := make([]byte, 1024)
|
||||||
...
|
...
|
||||||
n, err := inputReader.Read(buf)
|
n, err := inputReader.Read(buf)
|
||||||
if (n == 0) { break}
|
if (n == 0) { break}
|
||||||
```
|
```
|
||||||
|
|
||||||
变量 n 的值表示读取到的字节数.
|
变量 n 的值表示读取到的字节数.
|
||||||
|
|
||||||
**3) 按列读取文件中的数据**
|
**3) 按列读取文件中的数据**
|
||||||
@@ -94,6 +98,7 @@ if (n == 0) { break}
|
|||||||
如果数据是按列排列并用空格分隔的,你可以使用 `fmt` 包提供的以 FScan 开头的一系列函数来读取他们。请看以下程序,我们将 3 列的数据分别读入变量 v1、v2 和 v3 内,然后分别把他们添加到切片的尾部。
|
如果数据是按列排列并用空格分隔的,你可以使用 `fmt` 包提供的以 FScan 开头的一系列函数来读取他们。请看以下程序,我们将 3 列的数据分别读入变量 v1、v2 和 v3 内,然后分别把他们添加到切片的尾部。
|
||||||
|
|
||||||
示例 12.6 [read_file2.go](examples/chapter_12/read_file2.go):
|
示例 12.6 [read_file2.go](examples/chapter_12/read_file2.go):
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
import (
|
import (
|
||||||
@@ -136,6 +141,7 @@ func main() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
**注意:** `path` 包里包含一个子包叫 `filepath`,这个子包提供了跨平台的函数,用于处理文件名和路径。例如 Base() 函数用于获得路径中的最后一个元素(不包含后面的分隔符):
|
**注意:** `path` 包里包含一个子包叫 `filepath`,这个子包提供了跨平台的函数,用于处理文件名和路径。例如 Base() 函数用于获得路径中的最后一个元素(不包含后面的分隔符):
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "path/filepath"
|
import "path/filepath"
|
||||||
filename := filepath.Base(path)
|
filename := filepath.Base(path)
|
||||||
@@ -144,6 +150,7 @@ filename := filepath.Base(path)
|
|||||||
**练习 12.3**:[read_csv.go](exercises/chapter_12/read_csv.go)
|
**练习 12.3**:[read_csv.go](exercises/chapter_12/read_csv.go)
|
||||||
|
|
||||||
文件 products.txt 的内容如下:
|
文件 products.txt 的内容如下:
|
||||||
|
|
||||||
```
|
```
|
||||||
"The ABC of Go";25.5;1500
|
"The ABC of Go";25.5;1500
|
||||||
"Functional Programming with Go";56;280
|
"Functional Programming with Go";56;280
|
||||||
@@ -161,6 +168,7 @@ filename := filepath.Base(path)
|
|||||||
下面的程序展示了如何读取一个 gzip 文件。
|
下面的程序展示了如何读取一个 gzip 文件。
|
||||||
|
|
||||||
示例 12.7 [gzipped.go](examples/chapter_12/gzipped.go):
|
示例 12.7 [gzipped.go](examples/chapter_12/gzipped.go):
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
|
|
||||||
@@ -203,6 +211,7 @@ func main() {
|
|||||||
请看以下程序:
|
请看以下程序:
|
||||||
|
|
||||||
示例 12.8 [fileoutput.go](examples/chapter_12/fileoutput.go):
|
示例 12.8 [fileoutput.go](examples/chapter_12/fileoutput.go):
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
|
|
||||||
@@ -244,10 +253,10 @@ outputFile, outputError := os.OpenFile(“output.dat”, os.O_WRONLY|os.O_ CREAT
|
|||||||
|
|
||||||
我们通常会用到以下标志:
|
我们通常会用到以下标志:
|
||||||
|
|
||||||
`os.O_RDONLY`:只读
|
- `os.O_RDONLY`:只读
|
||||||
`os.WRONLY`:只写
|
- `os.WRONLY`:只写
|
||||||
`os.O_CREATE`:创建:如果指定文件不存在,就创建该文件。
|
- `os.O_CREATE`:创建:如果指定文件不存在,就创建该文件。
|
||||||
`os.O_TRUNC`:截断:如果指定文件已存在,就将该文件的长度截为0。
|
- `os.O_TRUNC`:截断:如果指定文件已存在,就将该文件的长度截为0。
|
||||||
|
|
||||||
在读文件的时候,文件的权限是被忽略的,所以在使用 `OpenFile` 时传入的第三个参数可以用0。而在写文件时,不管是 Unix 还是 Windows,都需要使用 0666。
|
在读文件的时候,文件的权限是被忽略的,所以在使用 `OpenFile` 时传入的第三个参数可以用0。而在写文件时,不管是 Unix 还是 Windows,都需要使用 0666。
|
||||||
|
|
||||||
@@ -266,6 +275,7 @@ outputWriter := bufio.NewWriter(outputFile)
|
|||||||
程序 `filewrite.go` 展示了不使用 `fmt.FPrintf` 函数,使用其他函数如何写文件:
|
程序 `filewrite.go` 展示了不使用 `fmt.FPrintf` 函数,使用其他函数如何写文件:
|
||||||
|
|
||||||
示例 12.8 [filewrite.go](examples/chapter_12/filewrite.go):
|
示例 12.8 [filewrite.go](examples/chapter_12/filewrite.go):
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
|
|
||||||
@@ -300,8 +310,7 @@ type Page struct {
|
|||||||
|
|
||||||
请给这个结构编写一个 `save` 方法,将 Title 作为文件名、Body作为文件内容,写入到文本文件中。
|
请给这个结构编写一个 `save` 方法,将 Title 作为文件名、Body作为文件内容,写入到文本文件中。
|
||||||
|
|
||||||
再编写一个 `load` 函数,接收的参数是字符串 title,该函数读取出与 title 对应的文本文件。请使用 *Page 做为参数,因为这个结构可能相当巨大,我们不想在内存中拷贝它。请使用 `ioutil` 包里的函数(参考章节12.2.1)。
|
再编写一个 `load` 函数,接收的参数是字符串 title,该函数读取出与 title 对应的文本文件。请使用 `*Page` 做为参数,因为这个结构可能相当巨大,我们不想在内存中拷贝它。请使用 `ioutil` 包里的函数(参考章节12.2.1)。
|
||||||
|
|
||||||
|
|
||||||
## 链接
|
## 链接
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user