ZetCode

Go 读取文件

最后修改时间 2024 年 4 月 11 日

在本文中,我们将展示如何在 Golang 中读取文件。我们读取文本文件和二进制文件。了解如何在 Go 中写入文件,请访问 Go 写入文件

要在 Go 中读取文件,我们使用 osioutiliobufio 包。

thermopylae.txt
The Battle of Thermopylae was fought between an alliance of Greek city-states,
led by King Leonidas of Sparta, and the Persian Empire of Xerxes I over the
course of three days, during the second Persian invasion of Greece.

我们在一些示例中使用此文本文件。

Go 将文件读取到字符串

ioutil.ReafFile 函数将整个文件读取到一个字符串中。此函数很方便,但不适用于非常大的文件。

read_file.go
package main

import (
    "fmt"
    "io/ioutil"
    "log"
)

func main() {

    content, err := ioutil.ReadFile("thermopylae.txt")

     if err != nil {
          log.Fatal(err)
     }

    fmt.Println(string(content))
}

该示例读取整个文件并将其打印到控制台。

$ go run read_file.go
The Battle of Thermopylae was fought between an alliance of Greek city-states,
led by King Leonidas of Sparta, and the Persian Empire of Xerxes I over the
course of three days, during the second Persian invasion of Greece.

Go 逐行读取文件

Scanner 为读取数据(例如,文本文件中的换行符分隔行)提供了一个方便的接口。它按标记读取数据;Split 函数定义了标记。默认情况下,该函数按行拆分数据,并去除行尾符。

read_line_by_line.go
package main

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

func main() {

    f, err := os.Open("thermopylae.txt")

    if err != nil {
        log.Fatal(err)
    }

    defer f.Close()

    scanner := bufio.NewScanner(f)

    for scanner.Scan() {

        fmt.Println(scanner.Text())
    }

    if err := scanner.Err(); err != nil {
        log.Fatal(err)
    }
}

该示例逐行读取文件。每一行都会被打印出来。

f, err := os.Open("thermopylae.txt")

Open 函数打开文件进行读取。

defer f.Close()

文件描述符将在 main 函数结束时关闭。

scanner := bufio.NewScanner(f)

创建一个新的扫描器。

for scanner.Scan() {

     fmt.Println(scanner.Text())
}

Scan 将扫描器推进到下一个标记,该标记随后可以通过 BytesText 函数获取。

Go 按单词读取文件

扫描器的默认拆分函数是 ScanLines。使用 SplitWords,我们将内容按单词拆分。

read_by_word.go
package main

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

func main() {

    f, err := os.Open("thermopylae.txt")

    if err != nil {
        fmt.Println(err)
     }

    defer f.Close()

    scanner := bufio.NewScanner(f)
    scanner.Split(bufio.ScanWords)

    for scanner.Scan() {

        fmt.Println(scanner.Text())
    }

    if err := scanner.Err(); err != nil {
        fmt.Println(err)
    }
}

该示例逐个单词读取文件。

$ go run read_by_word.go
The
Battle
of
Thermopylae
was
fought
between
...

Go 块状读取文件

我们可以分块读取文件。

read_in_chunks.go
package main

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

func main() {

    f, err := os.Open("thermopylae.txt")

    if err != nil {
         log.Fatal(err)
    }

    defer f.Close()

    reader := bufio.NewReader(f)
    buf := make([]byte, 16)

    for {
        n, err := reader.Read(buf)

        if err != nil {

           if err != io.EOF {

               log.Fatal(err)
           }

           break
        } 

        fmt.Print(string(buf[0:n]))
    }

    fmt.Println()
}

该示例以 16 字节的小块读取文件。

buf := make([]byte, 16)

我们定义一个 16 字节的数组。

for {
    n, err := reader.Read(buf)

    if err != nil {

         if err != io.EOF {

             log.Fatal(err)
         }

         break
    }

    fmt.Print(string(buf[0:n]))
}

在 for 循环中,我们使用 Read 将数据读入缓冲区,并使用 Print 将数组缓冲区打印到控制台。

Go 读取二进制文件

hex 包实现了十六进制编码和解码。

read_binary_file.go
package main

import (  
    "bufio"
    "encoding/hex"
    "fmt"
    "log"
    "os"
    "io"
)

func main() {  

    f, err := os.Open("sid.jpg")

    if err != nil {
        log.Fatal(err)
    }

    defer f.Close()

    reader := bufio.NewReader(f)
    buf := make([]byte, 256)

    for {
        _, err := reader.Read(buf)

        if err != nil {
            if err != io.EOF {
                fmt.Println(err)
            }
            break
        }
        
        fmt.Printf("%s", hex.Dump(buf))
    }
}

在代码示例中,我们读取一个图像并以十六进制格式打印它。

fmt.Printf("%s", hex.Dump(buf))

Dump 返回一个包含给定数据的十六进制转储的字符串。

$ go run read_binary_file.go
00000000  ff d8 ff e0 00 10 4a 46  49 46 00 01 01 00 00 01  |......JFIF......|
00000010  00 01 00 00 ff e1 00 2f  45 78 69 66 00 00 49 49  |......./Exif..II|
00000020  2a 00 08 00 00 00 01 00  0e 01 02 00 0d 00 00 00  |*...............|
00000030  1a 00 00 00 00 00 00 00  6b 69 6e 6f 70 6f 69 73  |........kinopois|
00000040  6b 2e 72 75 00 ff fe 00  3b 43 52 45 41 54 4f 52  |k.ru....;CREATOR|
00000050  3a 20 67 64 2d 6a 70 65  67 20 76 31 2e 30 20 28  |: gd-jpeg v1.0 (|
00000060  75 73 69 6e 67 20 49 4a  47 20 4a 50 45 47 20 76  |using IJG JPEG v|
00000070  38 30 29 2c 20 71 75 61  6c 69 74 79 20 3d 20 39  |80), quality = 9|
00000080  31 0a ff db 00 43 00 03  02 02 03 02 02 03 03 02  |1....C..........|
00000090  03 03 03 03 03 04 07 05  04 04 04 04 09 06 07 05  |................|
000000a0  07 0a 09 0b 0b 0a 09 0a  0a 0c 0d 11 0e 0c 0c 10  |................|
000000b0  0c 0a 0a 0e 14 0f 10 11  12 13 13 13 0b 0e 14 16  |................|
...  

来源

Go os 包 - 参考

在本文中,我们介绍了如何在 Go 中读取文件。

作者

我叫 Jan Bodnar,我是一名充满激情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。至今,我已撰写了 1400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出所有 Go 教程