終端讀寫
之前常使用的fmt包,就是操作終端的代表
操作終端 相關文件句柄 常量
os.Stdin
:標準輸入
os.Stdout
:標準輸出
os.Stderr
:標準錯誤輸出
Fprintln(Fprintf)搭配os實現終端寫入 fmt.Println(io.Writer, a ...interface{})
第一個參數為一個實現io.Writer接口的實例
第二個參數為內容
1 2 3 4 5 6 7 8 9 10 package mainimport ( "fmt" "os" ) func main () { fmt.Fprintln(os.Stdout,"Hello World" ) }
其中的os.Stdout
實現了io.Writer
這個接口,因此可作為參數被傳入
result
可以發現其功能與fmt.Println()
直接輸出的功能是一樣的
Scanln(Scanf)實現終端讀入 可使用Scanln()
實現單行從終端讀入,其等價於Scanf()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 func testScanln () { var a int var b string fmt.Printf("input int & string:" ) fmt.Scanln(&a,&b) fmt.Fprintf(os.Stdout,"int:%d, string:%s" ,a,b) } func main () { testScanln() } `` `` * 其`fmt.Scanln(&a,&b)` 等同於`fmt.Scanf(%d %s,a,b)` ### result `` `command > input int & string:1234 Hello!! > int:1234, string:Hello!!
Sscanf實現字符串格式化讀入 將特定的字符串格式化讀入,並賦值給不同的變量
1 2 3 4 5 6 7 8 9 10 11 12 func testSscanf () { var a int var b string var c float64 str := "18 Hello 12.3" fmt.Sscanf(str,"%d %s %f" , &a, &b, &c) fmt.Fprintf(os.Stdout,"int:%d, string:%s, float:%.2f" , a, b, c) } func main () { testSscanf() }
fmt.Sscanf(string, format, ...variables)
:
第一個參數為要讀入的字符串(string)
第二個參數為要讀入的格式(format)
第三個參數為可變參數,將讀入的值賦給各個變量(…variables)
result 1 int:18, string:Hello, float:12.30
文件讀寫 套用終端讀寫使用的Fprintln()
方法,只要將實現io.Writer
接口的文件句柄傳參亦能實現讀寫文件的功能
建立(Write)文件句柄 使用os.OpenFile()
方法來開啟文件,且其賦值的變量就為文件句柄 os.OpenFile()
方法通常用作寫文件
1 file,err := os.OpenFile("test.log" , os.O_CREATE|os.O_WRONLY, 0664 )
example 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package mainimport ( "os" "fmt" ) func main () { file,err := os.OpenFile("/tmp/test.log" ,os.O_CREATE|os.O_WRONLY,0664 ) if err != nil { fmt.Println("OpenFile Failed !, Error:" ,err) return } defer file.Close() fmt.Fprintln(file,"Test WritingFile!!" ) }
result 1 2 > cat /tmp/test.log test.log > Test WritingFile!!
從上述結果可以知道File
這個變量亦實現了io.Writer
接口,才能作為參數被傳入到Fprintln()函數中
建立(Read)文件句柄 使用os.Open()
方法來開啟文件os.Open()
方法通常用作讀文件
1 file,err := os.Open("test.log" )
只有一個參數,要是沒有填寫路徑預設會打開在GoPATH底下的同名文件
ioutil文件讀寫 位於io/ioutil
包中,可將整個文件直接讀取或是直接寫入
讀操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 func testIoutilRead (FileName string ) { file,err := ioutil.ReadFile(FileName) if err != nil { fmt.Fprintf(os.Stderr,"File Error: %s" ,err) return } fmt.Println(string (file)) } func main () { testIoutilRead("Testlog.log" ) }
result
寫操作 1 2 3 4 5 6 7 8 9 10 11 12 13 func testIoutilWrite (FileName string ) { err := ioutil.WriteFile(FileName,[]byte ("Writing..." ),0664 ) if err != nil { fmt.Fprintf(os.Stderr,"File Write Error:" ,err) return } } func main () { testIoutilWrite("/tmp/test.log" ) }
ioutil.WriteFile
只有一個錯誤的返回值
請注意寫入多data為[]byte
類型
第三個參數為權限設置
result 1 2 > cat /tmp/test.log > Writing...
帶緩衝區(bufio)的讀寫 不直接操作底層的io(包括文件或是終端),而是將數據先寫入緩衝區,再由Golang或是操作系統將緩衝區的數據寫入文件中
一般會先寫入到緩衝區中主要是為了性能,因為直接操作存放在硬碟的文件比記憶體的效率差很多
從終端讀入 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 func testbufio_terminalRead () { bufioRead := bufio.NewReader(os.Stdin) fmt.Printf("input something I can read:" ) str,err := bufioRead.ReadBytes('\n' ) if err != nil { fmt.Println("Terminal Read FAILED!!:" ,err) return } fmt.Println(string (str)) } func main () { testbufio_terminalRead() }
請注意bufio.NewReader()
創造的實例有很多方法可以自己嘗試
亦可將os.Stdin
替換成其他實現io.Reader
接口的實例,實現不同的讀操作(文件,網路等)
result 1 2 > input something I can read:You have to read this sentence > You have to read this sentence
從文件讀入 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 func testbufio_FileRead (FileName string ) { file, err := os.Open(FileName) if err != nil { fmt.Println("file open failed with Error:" , err) return } defer file.Close() bufioRead := bufio.NewReader(file) for { line,err := bufioRead.ReadString('\n' ) if err == io.EOF { fmt.Println("The End" ) return } if err != nil && err != io.EOF { fmt.Println("ReadLine Error:" ,err) return } fmt.Printf(line) } } func main () { testbufio_FileRead("Testlog.log" ) }
result 1 2 Test Hello World The End
os.File os.File
是一個結構體(struct) 之前提到的os.Stdin
,os.Stdout
,os.Stderr
,file文件句柄都屬於os.File
的指針類型
寫入文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 func testbufioWrite (FileName string ) { file,err := os.OpenFile(FileName,os.O_WRONLY|os.O_CREATE,0664 ) if err != nil { fmt.Fprintf(os.Stderr,"File Open Error:%s" ,err) return } defer file.Close() writer := bufio.NewWriter(file) writer.WriteString("test bufio writing..." ) writer.Flush() } func main () { testbufioWrite("bufioWritingTest.log" ) }
讀取壓縮文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 func testReadgzip (FileName string ) { fi, err := os.Open(FileName) if err != nil { fmt.Fprintf(os.Stderr,"Open file err : %s" ,err) os.Exit(1 ) return } defer fi.Close() gz,err := gzip.NewReader(fi) if err != nil { fmt.Fprintf(os.Stderr,"ungzip Failed: %s" ,err) return } r := bufio.NewReader(gz) for { line,err := r.ReadString('\n' ) if err != nil && err == io.EOF { fmt.Fprintf(os.Stdout,"File Read Finish" ) return } fmt.Print(line) } } func main () { testReadgzip("Testlog.log.gz" ) }
result 1 2 Test Hello World File Read Finish
拷貝文件 拷貝文件使用io.Copy(dst Writer, src Reader)(written int64, err error)
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 func TestCopy (dst_file,src_file string ) (written int64 ,err error) { src,err := os.Open(src_file) if err != nil { fmt.Fprintf(os.Stderr,"dst File open Failed:" ,err) return } defer src.Close() dst,err := os.OpenFile(dst_file,os.O_CREATE|os.O_WRONLY,0666 ) if err != nil { fmt.Fprintf(os.Stderr,"src File open Failed:" ,err) return } defer dst.Close() return io.Copy(dst,src) } func main () { _ ,err := TestCopy("new_dst_file.go" ,"test2.go" ) if err != nil { fmt.Fprintf(os.Stderr,"Copy Failed:%s" ,err) return } fmt.Println("Copy sucess" ) }
result