12.2 文件读写

12.2.1 读文件

os.Fileos.Stdinos.Stdout*os.File

示例 12.4 fileinput.go:

package main

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

func main() {
    inputFile, inputError := os.Open("input.dat")
    if inputError != nil {
        fmt.Printf("An error occurred on opening the inputfile\n" +
            "Does the file exist?\n" +
            "Have you got acces to it?\n")
        return // exit the function on error
    }
    defer inputFile.Close()

    inputReader := bufio.NewReader(inputFile)
    for {
        inputString, readerError := inputReader.ReadString('\n')
        fmt.Printf("The input was: %s", inputString)
        if readerError == io.EOF {
            return
        }      
    }
}
inputFile*os.FileosOpenstringinput.dat
inputFile, inputError = os.Open("input.dat")defer inputFile.Close()bufio.NewReader
bufio
ReadString('\n')ReadBytes('\n')
ReadStringReadBytesReadLine()
readerErrorio.EOFreturn

其他类似函数:

1) 将整个文件的内容读到一个字符串里:

io/ioutilioutil.ReadFile()[]byteWriteFile()[]byte
package main
import (
    "fmt"
    "io/ioutil"
    "os"
)

func main() {
    inputFile := "products.txt"
    outputFile := "products_copy.txt"
    buf, err := ioutil.ReadFile(inputFile)
    if err != nil {
        fmt.Fprintf(os.Stderr, "File Error: %s\n", err)
        // panic(err.Error())
    }
    fmt.Printf("%s\n", string(buf))
    err = ioutil.WriteFile(outputFile, buf, 0644) // oct, not hex
    if err != nil {
        panic(err.Error())
    }
}

2) 带缓冲的读取

ReadString()bufio.ReaderRead()
buf := make([]byte, 1024)
...
n, err := inputReader.Read(buf)
if (n == 0) { break}

变量 n 的值表示读取到的字节数.

3) 按列读取文件中的数据

fmt

示例 12.6 read_file2.go:

package main
import (
    "fmt"
    "os"
)

func main() {
    file, err := os.Open("products2.txt")
    if err != nil {
        panic(err)
    }
    defer file.Close()

    var col1, col2, col3 []string
    for {
        var v1, v2, v3 string
        _, err := fmt.Fscanln(file, &v1, &v2, &v3)
        // scans until newline
        if err != nil {
            break
        }
        col1 = append(col1, v1)
        col2 = append(col2, v2)
        col3 = append(col3, v3)
    }

    fmt.Println(col1)
    fmt.Println(col2)
    fmt.Println(col3)
}

输出结果:

[ABC FUNC GO]
[40 56 45]
[150 280 356]
pathfilepath
import "path/filepath"
filename := filepath.Base(path)

练习 12.3:read_csv.go

文件 products.txt 的内容如下:

"The ABC of Go";25.5;1500
"Functional Programming with Go";56;280
"Go for It";45.9;356
"The Go Way";55;500

每行的第一个字段为 title,第二个字段为 price,第三个字段为 quantity。内容的格式基本与 示例 12.3c 的相同,除了分隔符改成了分号。请读取出文件的内容,创建一个结构用于存取一行的数据,然后使用结构的切片,并把数据打印出来。

encoding/csv

12.2.2 包:读取压缩文件

compress

下面的程序展示了如何读取一个 gzip 文件。

示例 12.7 gzipped.go:

package main

import (
	"fmt"
	"bufio"
	"os"
	"compress/gzip"
)

func main() {
	fName := "MyFile.gz"
	var r *bufio.Reader
	fi, err := os.Open(fName)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v, Can't open %s: error: %s\n", os.Args[0], fName,
			err)
		os.Exit(1)
	}
	fz, err := gzip.NewReader(fi)
	if err != nil {
		r = bufio.NewReader(fi)
	} else {
		r = bufio.NewReader(fz)
	}

	for {
		line, err := r.ReadString('\n')
		if err != nil {
			fmt.Println("Done reading file")
			os.Exit(0)
		}
		fmt.Println(line)
	}
}

12.2.3 写文件

请看以下程序:

示例 12.8 fileoutput.go:

package main

import (
	"os"
	"bufio"
	"fmt"
)

func main () {
	// var outputWriter *bufio.Writer
	// var outputFile *os.File
	// var outputError os.Error
	// var outputString string
	outputFile, outputError := os.OpenFile("output.dat", os.O_WRONLY|os.O_CREATE, 0666)
	if outputError != nil {
		fmt.Printf("An error occurred with file opening or creation\n")
		return  
	}
	defer outputFile.Close()

	outputWriter := bufio.NewWriter(outputFile)
	outputString := "hello world!\n"

	for i:=0; i<10; i++ {
		outputWriter.WriteString(outputString)
	}
	outputWriter.Flush()
}
bufioWriteroutput.dat
outputFile, outputError := os.OpenFile("output.dat", os.O_WRONLY|os.O_CREATE, 0666)
OpenFile

我们通常会用到以下标志:

os.O_RDONLYos.O_WRONLYos.O_CREATEos.O_TRUNC
OpenFile

然后,我们创建一个写入器(缓冲区)对象:

outputWriter := bufio.NewWriter(outputFile)
outputWriter.WriteString(outputString)
outputWriter.Flush()
fmt.Fprintf(outputFile, "Some test data.\n")fmtio.Writer
filewrite.gofmt.FPrintf

示例 12.8 filewrite.go:

package main

import "os"

func main() {
	os.Stdout.WriteString("hello, world\n")
	f, _ := os.OpenFile("test", os.O_CREATE|os.O_WRONLY, 0666)
	defer f.Close()
	f.WriteString("hello, world in a file\n")
}
os.Stdout.WriteString("hello, world\n")
f, _ := os.OpenFile("test", os.O_CREATE|os.O_WRONLY, 0666)
f.WriteString( )

练习 12.4:wiki_part1.go

(这是一个独立的练习,但是同时也是为章节15.4做准备)

程序中的数据结构如下,是一个包含以下字段的结构:

type Page struct {
    Title string
    Body  []byte
}
save
load*Pageioutil

链接