Go語言讀取文件的方法小結(jié)
寫程序時(shí)經(jīng)常需要從一個(gè)文件讀取數(shù)據(jù),然后輸出到另一個(gè)文件。最典型的例子比如,從stdin讀取,然后輸出到stdout。go提供了幾種讀取文件的方式,我們逐個(gè)來看一看~
fmt.Scan
func fmtScan() {
str := ""
for {
fmt.Scan(&str)
fmt.Printf("[fmt.scan]: %q (%d)\n", str, len(str))
}
}
// input: abc def ghi
// output:
//[fmt.scan]: "abc" (3)
//[fmt.scan]: "def" (3)
//[fmt.scan]: "ghi" (3)
fmt.Scan 從stdin讀取數(shù)據(jù),輸出到內(nèi)存變量。它會(huì)將空白符作為分割符,把分割后的字符串,依次賦值給傳入?yún)?shù)。在上面的例子中,就是循環(huán)了3次分別賦值給str。
os.Stdin.Read
func osStdinRead() {
p := make([]byte, 5)
for {
nn, err := os.Stdin.Read(p)
if err != nil && err != io.EOF {
panic(err)
}
fmt.Printf("[os.stdin.read]: %q (%d)\n", p, nn)
p = make([]byte, 5) // 清空p
}
}
// input: abcdefghijk
// output:
//[os.stdin.read]: "abcde" (5)
//[os.stdin.read]: "fghij" (5)
//[os.stdin.read]: "k\n\x00\x00\x00" (2)
最多讀取len(p)大小的數(shù)據(jù),如果輸入的內(nèi)容超出了len(p),則Read會(huì)在下一輪循環(huán)中接著讀取。
io系列
ReadAll
func ioReadAll() {
for {
p, err := io.ReadAll(os.Stdin)
if err != nil {
panic(err)
}
fmt.Printf("[io.ReadAll]: %q (%d)\n", p, len(p))
}
}
// input: abc\nEOF
// output: [io.ReadAll]: "abc\n" (4)
ReadAll 讀取全部,不把EOF當(dāng)作錯(cuò)誤返回。
ReadFull
func ioReadFull() {
p := make([]byte, 5)
for {
nn, err := io.ReadFull(os.Stdin, p)
if err != nil && err != io.EOF {
fmt.Printf("[io.ReadFull]: %q (%d)\n", p, nn)
panic(err)
}
fmt.Printf("[io.ReadFull]: %q (%d)\n", p, nn)
p = make([]byte, 5)
}
}
// input: aaaaaa
// output: [io.ReadFull]: "aaaaa" (5)
// input: aa\n\x00
// output: [io.ReadFull]: "aa\n\x00\x00" (3)
ReadFull 的目標(biāo)是把p填滿,也就是說正常情況下只有讀到的數(shù)據(jù)長度nn==len(p)才返回。這里有兩種情況需要注意:
- 沒有數(shù)據(jù)可讀,ReadFull返回 (0, EOF)
- 有一些數(shù)據(jù)可讀,但在填滿p前遇到了EOF,ReadFull返回 (讀取的長度, ErrUnexpectedEOF)
bufio系列
bufio給io操作提供了一個(gè)緩沖,避免了每次都要訪問磁盤。
Read
func bufioRead() {
br := bufio.NewReader(os.Stdin)
p := make([]byte, 5)
for {
nn, err := br.Read(p)
if err != nil && err != io.EOF{
panic(err)
}
fmt.Printf("[bufio.read]: %q (%d)\n", p, nn)
}
}
// input: abcdefghijk
// output:
//[bufio.read]: "abcde" (5)
//[bufio.read]: "fghij" (5)
//[bufio.read]: "k\n\x00\x00\x00" (2)
最多讀取len(p)大小的數(shù)據(jù),如果輸入的內(nèi)容超出了len(p),則Read會(huì)在下一輪循環(huán)中接著讀取。
ReadBytes
func bufioReadBytes() {
br := bufio.NewReader(os.Stdin)
for {
p, err := br.ReadBytes('\n')
if err != nil && err != io.EOF{
panic(err)
}
fmt.Printf("[bufio.ReadBytes]: %q (%d)\n", p, len(p))
}
}
// input: abcdef
// output: [bufio.ReadBytes]: "abcdef\n" (7)
ReadBytes 讀取直到遇到給定的分界符,這里是'\n'(返回的p包含\n)。如果在讀到分界符之前遇到了err,則返回讀到的數(shù)據(jù)和err(一般是EOF)。
ReadString
func bufioReadString() {
br := bufio.NewReader(os.Stdin)
for {
str, err := br.ReadString('\n')
if err != nil && err != io.EOF {
panic(err)
}
fmt.Printf("[bufio.ReadString]: %q (%d)\n", str, len(str))
}
}
// input: abcdef
// output: [bufio.ReadString]: "abcdef\n" (7)
ReadString 與 ReadBytes 類似,都是直到讀到分界符才返回。
ReadRune
func bufioReadRune() {
br := bufio.NewReader(os.Stdin)
for {
r, sz, err := br.ReadRune()
if err != nil && err != io.EOF {
panic(err)
}
fmt.Printf("[bufio.ReadRune]: %q (%d)\n", r, sz)
}
}
// input: abc
// output:
//[bufio.ReadRune]: 'a' (1)
//[bufio.ReadRune]: 'b' (1)
//[bufio.ReadRune]: 'c' (1)
//[bufio.ReadRune]: '\n' (1)
ReadRune 一次讀取一個(gè)UTF8字符。
Scan
func bufioScan() {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
text := scanner.Text()
fmt.Printf("[bufio.Scan]: %q (%d)\n", text, len(text))
}
if scanner.Err() != nil {
fmt.Print(scanner.Err().Error())
}
}
Scan 掃描文件到下一個(gè)token并返回true,隨后可以通過Text,Bytes讀取token。當(dāng)掃描停止時(shí),Scan返回false,這時(shí)可以通過Err獲取錯(cuò)誤,如果是因?yàn)镋OF而掃描停止,Err=nil。
scanner在創(chuàng)建時(shí),默認(rèn)使用 ScanLines 作為分割函數(shù)。它會(huì)將輸入文本分割成一系列的行,每行作為一個(gè)token。除此之外還有其他分割函數(shù):
ScanLines(默認(rèn)):按行分割。ScanWords:按空白字符分割的單詞。ScanBytes:按字節(jié)分割。ScanRunes:按UTF-8編碼的字符分割。
總結(jié)
如果只是簡單從stdin讀取,fmt.Scan 足夠短小好用。當(dāng)文件很大時(shí) io.ReadAll, io.ReadFull 感覺在使用時(shí)不是很靈活,還是推薦用bufio的一系列方法操作。
到此這篇關(guān)于Go語言讀取文件的方法小結(jié)的文章就介紹到這了,更多相關(guān)Go讀取文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用go進(jìn)行云存儲(chǔ)上傳實(shí)現(xiàn)實(shí)例
這篇文章主要為大家介紹了使用go進(jìn)行云存儲(chǔ)上傳實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪<BR>2024-01-01
Golang的Crypto/SHA256庫實(shí)戰(zhàn)指南
無論是在保護(hù)數(shù)據(jù)安全、驗(yàn)證數(shù)據(jù)完整性,還是在構(gòu)建復(fù)雜的安全系統(tǒng)中,crypto/sha256都是Golang程序員不可或缺的工具,本文主要介紹了Golang的Crypto/SHA256庫實(shí)戰(zhàn)指南,感興趣的可以了解一下2024-02-02
vscode配置go開發(fā)環(huán)境的實(shí)戰(zhàn)過程
vscode配置go的開發(fā)環(huán)境很簡單,下面這篇文章主要給大家介紹了關(guān)于vscode配置go開發(fā)環(huán)境的實(shí)戰(zhàn)過程,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06

