前言
這篇文章将讨論如何在 Golang 中讀取檔案。我們将使用以下包來處理這些檔案。
- os 包提供了一個獨立于平台的接口來執行操作級操作。
- IOutil 軟體包提供了易于使用的實用程式函數來處理檔案,而無需了解太多内部實作。
- bufio 包實作了緩沖 IO,這有助于我們提高輸入和輸出操作的性能和吞吐量。
- log 包實作一個簡單的日志記錄包。我們将在整個程式中使用它。我們将在程式中使用日志包的 Fatal() 函數。
整個檔案讀取
我們可以很容易地一次性讀取整個檔案并将其存儲在一個變量中。但請記住,我們不應該對大檔案這樣做。我們将使用ioutil.ReadFile() 函數來讀取檔案并将檔案的内容存儲在一個變量中。
首先,讓我們在我們程式所在的同一目錄下存儲一個檔案。是以,我們的檔案夾結構将是下面這樣的。
css複制代碼___
|
|_ _ _ _ ilovego.txt |
|_ _ _ _ main.go
我們在 main.go 函數中寫入如下的内容:
go複制代碼package main
import (
"fmt"
"io/ioutil"
"log"
)
func main() {
content, err := ioutil.ReadFile("ilovego.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(content))
}
但首先,讓我們讨論一下 ReadFile() 函數的情況:
- 定義:方法聲明 func ReadFile(filename string) ([]byte, error)
- 功能:讀取路徑被傳入函數參數的檔案,并傳回檔案的内容。在内部使用 os.ReadFile(fileName) 方法
- 傳回:在一個位元組數組中傳回檔案的内容和錯誤。一個成功的調用将傳回 err == nil
内部 ReadFile 函數實作如下:
go複制代碼func ReadFile(filename string) ([]byte, error) {
return os.ReadFile(filename)
}
現在,讓我們回到我們的程式:
- ioutil.ReadFile("readthisfile.txt") 傳回一個 byteArray 和一個 err。我們将byteArray 存儲在 "content "變量中,錯誤存儲在 " err "變量中。
- 然後我們放置了一個 if 條件,如果 err 值不為 nil,我們将使用 log.Fatal() 函數列印錯誤 err 。記住,Fatal() 函數等同于 Print() 函數,然後調用 os.Exit(1) 。
- 最後,我們将使用 fmt.Println() 函數列印檔案的内容。 我們不能簡單地列印 content 變量,因為它是一個位元組數組,我們需要将它轉換為字元串: string(content)
然後建立一個 ilovego.txt 檔案,寫入如下内容:
csharp複制代碼I Love Golang,
This is One of the Best Languages on the World!
最後,執行上述代碼,可以看到如下輸出:
csharp複制代碼$ go run main.go
I Love Golang,
This is One of the Best Languages on the World!
按行讀取
Scanner 掃描器提供了一個友善的接口來讀取資料,比如一個由新行分隔的文本行組成的檔案。它通過标記來讀取資料;Split 函數定義了标記。預設情況下,該函數将資料分成幾行,并剝離了行端。
go複制代碼package main
import (
"fmt"
// "io/ioutil"
"bufio"
"log"
"os"
)
func main() {
// opening the file using Open function
f, err := os.Open("ilovego.txt")
if err != nil {
log.Fatal(err)
}
defer f.Close()
// create a scanner for the file
scanner := bufio.NewScanner(f)
// loop through the scanner until it return fasle
for scanner.Scan() {
fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
}
- os.Open() 打開參數中傳遞的檔案。如果在打開檔案時遇到任何錯誤,它将傳回同樣的錯誤。否則,錯誤将是 nil。
- 然後,我們使用掃描器來讀取檔案,并逐行掃描,直到檔案内容結束。
- 最後,我們要關閉該檔案。
執行程式,結果如下:
逐個單詞讀取
我們還可以通過逐個單詞來讀取檔案:
go複制代碼package main
import (
"bufio"
"fmt"
"os"
)
func main() {
f, err := os.Open("ilovego.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)
}
}
運作代碼:
csharp複制代碼$ go run main.go
I
Love
Golang,
This
is
One
of
the
Best
Languages
on
the
World!
以資料塊的形式讀取檔案
一次性讀取整個檔案似乎是一種簡單的方法,但有時我們需要從記憶體管理的角度使我們的程式得到一些優化。Golang 提供了一種分塊讀取檔案的方法,而不是整個或甚至逐行讀取。因為如果一行的大小太大,逐行讀取也可能是低效的。
go複制代碼package main
import (
"bufio"
"fmt"
"io"
"log"
"os"
)
func main() {
f, err := os.Open("ilovego.txt")
if err != nil {
log.Fatal(err)
}
defer f.Close()
reader := bufio.NewReader(f)
buf := make([]byte, 16)
for {
// reading a file upto buffer
n, err := reader.Read(buf)
if err != nil {
if err != io.EOF {
log.Fatal(err)
}
break
}
fmt.Print(string(buf[0:n]))
}
fmt.Println()
}
二進制讀取
hex 包實作了十六進制的編碼和解碼。
go複制代碼package main
import (
"bufio"
"encoding/hex"
"fmt"
"io"
"log"
"os"
)
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))
}
}
總結
本文介紹了 Go 語言讀取檔案的幾種方式,ioutil.ReadFile 函數将整個檔案讀成一個字元串。這個函數很友善,但不應該用于非常大的檔案。希望能對你有所幫助!
連結:https://juejin.cn/post/7218564871831240760