分享

读文件,写文件,行过滤器

 心平9bwburua3p 2017-04-14

读文件

代码实例

// 读写文件在很多程序中都是必须的基本任务。首先我们看看一
// 些读文件的例子。

package main

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

// 读取文件需要经常进行错误检查,这个帮助方法可以精简下面
// 的错误检查过程。
func check(e error) {
    if e != nil {
        panic(e)
    }
}

func main() {

    // 也许大部分基本的文件读取任务是将文件内容读取到
    // 内存中。
    dat, err := ioutil.ReadFile("/tmp/dat")
    check(err)
    fmt.Print(string(dat))

    // 你经常会想对于一个文件是怎么读并且读取到哪一部分
    // 进行更多的控制。对于这个任务,从使用 `os.Open`
    // 打开一个文件获取一个 `os.File` 值开始。
    f, err := os.Open("/tmp/dat")
    check(err)

    // 从文件开始位置读取一些字节。这里最多读取 5 个字
    // 节,并且这也是我们实际读取的字节数。
    b1 := make([]byte, 5)
    n1, err := f.Read(b1)
    check(err)
    fmt.Printf("%d bytes: %s\n", n1, string(b1))

    // 你也可以 `Seek` 到一个文件中已知的位置并从这个位置开
    // 始进行读取。
    o2, err := f.Seek(6, 0)
    check(err)
    b2 := make([]byte, 2)
    n2, err := f.Read(b2)
    check(err)
    fmt.Printf("%d bytes @ %d: %s\n", n2, o2, string(b2))

    // `io` 包提供了一些可以帮助我们进行文件读取的函数。
    // 例如,上面的读取可以使用 `ReadAtLeast` 得到一个更
    // 健壮的实现。
    o3, err := f.Seek(6, 0)
    check(err)
    b3 := make([]byte, 2)
    n3, err := io.ReadAtLeast(f, b3, 2)
    check(err)
    fmt.Printf("%d bytes @ %d: %s\n", n3, o3, string(b3))

    // 没有内置的回转支持,但是使用 `Seek(0, 0)` 实现。
    _, err = f.Seek(0, 0)
    check(err)

    // `bufio` 包实现了带缓冲的读取,这不仅对有很多小的读
    // 取操作的能提升性能,也提供了很多附加的读取函数。
    r4 := bufio.NewReader(f)
    b4, err := r4.Peek(5)
    check(err)
    fmt.Printf("5 bytes: %s\n", string(b4))

    // 任务结束后要关闭这个文件(通常这个操作应该在 `Open`
    // 操作后立即使用 `defer` 来完成)。
    f.Close()

}

运行程序

$ echo "hello" > /tmp/dat
$ echo "go" >>   /tmp/dat
$ go run reading-files.go 
hello
go
5 bytes: hello
2 bytes @ 6: go
2 bytes @ 6: go
5 bytes: hello

# 下面我们将看一下写入文件。

写文件

代码实例

// Go 写文件和我们前面看过的读操作有着相似的方式。

package main

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

func check(e error) {
    if e != nil {
        panic(e)
    }
}

func main() {

    // 开始,这里是展示如写入一个字符串(或者只是一些
    // 字节)到一个文件。
    d1 := []byte("hello\ngo\n")
    err := ioutil.WriteFile("/tmp/dat1", d1, 0644)
    check(err)

    // 对于更细粒度的写入,先打开一个文件。
    f, err := os.Create("/tmp/dat2")
    check(err)

    // 打开文件后,习惯立即使用 defer 调用文件的 `Close`
    // 操作。
    defer f.Close()

    // 你可以写入你想写入的字节切片
    d2 := []byte{115, 111, 109, 101, 10}
    n2, err := f.Write(d2)
    check(err)
    fmt.Printf("wrote %d bytes\n", n2)

    // `WriteString` 也是可用的。
    n3, err := f.WriteString("writes\n")
    fmt.Printf("wrote %d bytes\n", n3)

    // 调用 `Sync` 来将缓冲区的信息写入磁盘。
    f.Sync()

    // `bufio` 提供了和我们前面看到的带缓冲的读取器一
    // 样的带缓冲的写入器。
    w := bufio.NewWriter(f)
    n4, err := w.WriteString("buffered\n")
    fmt.Printf("wrote %d bytes\n", n4)

    // 使用 `Flush` 来确保所有缓存的操作已写入底层写入器。
    w.Flush()

}

运行程序

# 运行这端文件写入代码。
$ go run writing-files.go 
wrote 5 bytes
wrote 7 bytes
wrote 9 bytes

# 然后检查写入文件的内容。
$ cat /tmp/dat1
hello
go
$ cat /tmp/dat2
some
writes
buffered

# 下面我们将看一些文件 I/O 的想法,就像我们已经看过的 
# `stdin` 和 `stdout` 流。

行过滤器

代码实例

// 一个_行过滤器_ 在读取标准输入流的输入,处理该输入,然后
// 将得到一些的结果输出到标准输出的程序中是常见的一个功能。
// `grep` 和 `sed` 是常见的行过滤器。

// 这里是一个使用 Go 编写的行过滤器示例,它将所有的输入文字
// 转化为大写的版本。你可以使用这个模式来写一个你自己的 Go
// 行过滤器。
package main

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

func main() {

    // 对 `os.Stdin` 使用一个带缓冲的 scanner,让我们可以
    // 直接使用方便的 `Scan` 方法来直接读取一行,每次调用
    // 该方法可以让 scanner 读取下一行。
    scanner := bufio.NewScanner(os.Stdin)

    for scanner.Scan() {
        // `Text` 返回当前的 token,现在是输入的下一行。
        ucl := strings.ToUpper(scanner.Text())

        // 写出大写的行。
        fmt.Println(ucl)
    }

    // 检查 `Scan` 的错误。文件结束符是可以接受的,并且
    // 不会被 `Scan` 当作一个错误。
    if err := scanner.Err(); err != nil {
        fmt.Fprintln(os.Stderr, "error:", err)
        os.Exit(1)
    }
}

运行程序

# 试一下我们的行过滤器,首先创建多一个有小写行的文件。
$ echo 'hello'   > /tmp/lines
$ echo 'filter' >> /tmp/lines

# 然后使用行过滤器来得到大些的行。
$ cat /tmp/lines | go run line-filters.go
HELLO
FILTER
动手实践是学习 IT 技术最有效的方式! 开始实验

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约