Golang實現(xiàn)IO操作
1. 輸入輸出的底層原理
終端其實是一個文件(Linux下一切皆文件),相關(guān)實例如下:
- os.Stdin:標(biāo)準(zhǔn)輸出的文件實例,類型為*File
- os.Stdout:標(biāo)準(zhǔn)輸入的文件實例,類型為*File
- os.Stderr:標(biāo)準(zhǔn)錯誤輸出的文件實例,類型為*File
以文件方式操作終端:
package main import ( "os" ) func main() { var buf []byte os.Stdin.Read(buf[:]) //從標(biāo)準(zhǔn)輸入中讀取 os.Stdin.WriteString(string(buf)) //寫入標(biāo)準(zhǔn)輸入 }
2. 文件操作相關(guān)API
根據(jù)提供的文件名創(chuàng)建新的文件,返回一個文件對象,默認(rèn)權(quán)限0666,任何人可讀可寫,不可執(zhí)行,如果文件存在,則會截斷它(為空文件),如果成功,返回的文件對象可用于I/O;對應(yīng)的文件描述符具有O_RDWR模式。如果出錯,錯誤底層類型是*PathError。
func Create(name string) (file *File, err error)
NewFile使用給出的Unix文件描述符和名稱創(chuàng)建一個文件。
func NewFile(fd uintptr, name string) *File
只讀方式打開一個名稱為name文件。
func Open(name string) (file *File, err error)
打開一個名為name的文件,flag是打開方式,只讀或只寫,不存在創(chuàng)建等,perm文件權(quán)限。
func OpenFile(name string, flag int, perm FileMode) (file *File, err error)
在指定位置(相對于文件起始位置),寫入byte類型的數(shù)據(jù)到文件,它返回寫入的字節(jié)數(shù)和可能遇到的任何錯誤。如果返回值n!=len(b),本方法會返回一個非nil的錯誤。
func (f *File) WriteAt(b []byte, off int64) (n int, err error)
向文件中寫入string類型的信息到文件。
func (f *File) WriteString(s string) (ret int, err error)
從f中讀取最多l(xiāng)en(b)字節(jié)數(shù)的數(shù)據(jù)到b。
func (f *File) Read(b []byte) (n int, err error)
從f的指定位置(相對于文件起始位置),讀取len(b)字節(jié)數(shù)并寫入b。
func (f *File) ReadAt(b []byte, off int64) (n int, err error)
刪除name指定的文件或目錄。
func Remove(name string) error
3. 打開和關(guān)閉文件
os.Open()函數(shù)能夠打開一個文件,返回一個*File和一個err。對得到的文件實例調(diào)用close()方法能夠關(guān)閉文件。
package main import ( "log" "os" ) func main() { //只讀的方式打開文件 f, err := os.Open("./main.go") if err != nil { log.Println("open main.go file fail") return } //關(guān)閉文件 defer f.Close() }
4. 寫文件
package main import ( "log" "os" ) func main() { //可讀可寫的方式創(chuàng)建一個文件 f, err := os.Create("./xx.txt") if err != nil { log.Println("create file fail") return } defer f.Close() for i := 0; i < 5; i++ { f.Write([]byte("ab\n")) f.WriteString("ab\n") } }
5. 讀文件
文件讀取可以用file.Read()和file.ReadAt(),讀到文件末尾會返回io.EOF的錯誤。
package main import ( "fmt" "io" "log" "os" ) func main() { f, err := os.Open("./xx.txt") if err != nil { log.Println("open file fail") return } defer f.Close() var content []byte for { var buf [128]byte n, err := f.Read(buf[:]) if err == io.EOF { //讀到文件末尾 break } if err != nil { log.Println("Read file fail", err) return } content = append(content, buf[:n]...) //buf[:n]切片被打散傳入 } fmt.Println(string(content)) }
“…”的用法:三個點“...”其實是go的一種語法糖(糖衣語法)
- 第一個用法主要是用于函數(shù)有多個不定參數(shù)的情況,表示為可變參數(shù),可以接受任意個數(shù)但相同類型的參數(shù)。
- 第二個用法是slice可以被打散進行傳遞。
6. 拷貝文件
package main import ( "io" "log" "os" ) func main() { f1, err := os.Open("./xx.txt") if err != nil { log.Println("open xx.txt file fail", err) return } defer f1.Close() f2, err := os.Create("./abc.txt") if err != nil { log.Println("create file fail ", err) return } defer f2.Close() for { var buf [128]byte n, err := f1.Read(buf[:]) if err == io.EOF { log.Println("讀取完畢") break } if err != nil { return } f2.Write(buf[:n]) } }
7. bufio
- bufio包實現(xiàn)了帶緩沖區(qū)的讀寫,是對文件讀寫的封裝。
- bufio緩沖寫數(shù)據(jù)。
- bufio讀數(shù)據(jù) ,bufio先把數(shù)據(jù)讀/寫到緩沖區(qū),達到某一上限,會刷新到文件中,也可以強制刷新。
package main import ( "bufio" "fmt" "io" "log" "os" ) func wr() { f, err := os.OpenFile("./xxx.txt", os.O_CREATE|os.O_WRONLY, 0664) if err != nil { log.Println("open file fail ", err) return } defer f.Close() //獲取writer對象 writer := bufio.NewWriter(f) for i := 0; i < 5; i++ { writer.WriteString("hello\n") } //刷新緩沖區(qū),強制寫入 writer.Flush() } func rd() { f, err := os.Open("./xxx.txt") if err != nil { log.Println("open file fail") return } defer f.Close() //獲取reader對象 reader := bufio.NewReader(f) var content []byte for { line, _, err := reader.ReadLine() if err == io.EOF { log.Println("讀取完畢") break } if err != nil { return } content = append(content, line...) } fmt.Println(string(content)) } func main() { wr() rd() }
8. ioutil工具包
- 工具包寫文件
- 工具包讀文件
package main import ( "fmt" "io/ioutil" "log" ) func wr() { err := ioutil.WriteFile("./xxxx.txt", []byte("hello world!"), 0666) if err != nil { log.Println("err") return } } func rd() { data, err := ioutil.ReadFile("./xxxx.txt") if err != nil { log.Println("err") return } fmt.Println(string(data)) } func main() { wr() rd() }
9. 例子
實現(xiàn)cat命令
package main import ( "bufio" "flag" "fmt" "io" "log" "os" ) func cat(reader *bufio.Reader) { for { buf, err := reader.ReadBytes('\n') //注意是字符 if err == io.EOF { break } fmt.Fprintf(os.Stdout, "%s", string(buf)) } } func main() { flag.Parse() if flag.NArg() == 0 { cat(bufio.NewReader(os.Stdin)) } else { for i := 0; i < flag.NArg(); i++ { f, err := os.Open(flag.Arg(i)) if err != nil { log.Printf("open file %s fail, err %v\n", flag.Arg(i), err) continue } cat(bufio.NewReader(f)) f.Close() } } }
到此這篇關(guān)于Golang實現(xiàn)IO操作的文章就介紹到這了,更多相關(guān)Golang IO操作內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
sublime text3解決Gosublime無法自動補全代碼的問題
本文主要介紹了sublime text3解決Gosublime無法自動補全代碼的問題,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-01-01Golang在Mac、Linux、Windows下如何交叉編譯的實現(xiàn)
這篇文章主要介紹了Golang在Mac、Linux、Windows下如何交叉編譯的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03Go語言的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)JSON
本文主要介紹了Go語言的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)JSON,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-01-01Go?channel實現(xiàn)批量讀取數(shù)據(jù)
Go中的?channel?其實并沒有提供批量讀取數(shù)據(jù)的方法,需要我們自己實現(xiàn)一個,使用本文就來為大家大家介紹一下如何通過Go?channel實現(xiàn)批量讀取數(shù)據(jù)吧2023-12-12