Go 語言讀取文件的幾種方式
前言
這篇文章將討論如何在 Golang 中讀取文件。我們將使用以下包來處理這些文件。
-
os
(https://pkg.go.dev/os) 包提供了一個獨立於平臺的接口來執行操作級操作。 -
IOutil
(https://pkg.go.dev/io/ioutil) 軟件包提供了易於使用的實用程序函數來處理文件,而無需瞭解太多內部實現。 -
bufio
(https://pkg.go.dev/bufio) 包實現了緩衝 IO,這有助於我們提高輸入和輸出操作的性能和吞吐量。 -
log
(https://pkg.go.dev/log) 包實現一個簡單的日誌記錄包。我們將在整個程序中使用它。我們將在程序中使用日誌包的Fatal()
函數。
整個文件讀取
我們可以很容易地一次性讀取整個文件並將其存儲在一個變量中。但請記住,我們不應該對大文件這樣做。我們將使用ioutil.ReadFile()
函數來讀取文件並將文件的內容存儲在一個變量中。
首先,讓我們在我們程序所在的同一目錄下存儲一個文件。因此,我們的文件夾結構將是下面這樣的。
___
|
|_ _ _ _ ilovego.txt |
|_ _ _ _ main.go
我們在 main.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 函數實現如下:
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
文件,寫入如下內容:
I Love Golang,
This is One of the Best Languages on the World!
最後,執行上述代碼,可以看到如下輸出:
$ go run main.go
I Love Golang,
This is One of the Best Languages on the World!
按行讀取
Scanner 掃描器提供了一個方便的接口來讀取數據,比如一個由新行分隔的文本行組成的文件。它通過標記來讀取數據;Split
函數定義了標記。默認情況下,該函數將數據分成幾行,並剝離了行端。
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。 -
然後,我們使用掃描器來讀取文件,並逐行掃描,直到文件內容結束。
-
最後,我們要關閉該文件。
執行程序,結果如下:
逐個單詞讀取
我們還可以通過逐個單詞來讀取文件:
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)
}
}
運行代碼:
$ go run main.go
I
Love
Golang,
This
is
One
of
the
Best
Languages
on
the
World!
以數據塊的形式讀取文件
一次性讀取整個文件似乎是一種簡單的方法,但有時我們需要從內存管理的角度使我們的程序得到一些優化。Golang 提供了一種分塊讀取文件的方法,而不是整個或甚至逐行讀取。因爲如果一行的大小太大,逐行讀取也可能是低效的。
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
包實現了十六進制的編碼和解碼。
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
函數將整個文件讀成一個字符串。這個函數很方便,但不應該用於非常大的文件。希望能對你有所幫助!
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/4gqRsDkDDSaY-mUUwVmp0Q