1. 程式人生 > >Go語言學習筆記(十八)之檔案讀寫

Go語言學習筆記(十八)之檔案讀寫

25.檔案讀寫

1.檔案開啟和讀

A.檔案分類:文字和二進位制檔案
B.檔案存取方式:隨機存取和順序存取

檔案開啟程式碼示例:

  1: package main
  2: 
  3: import (
  4: 	"bufio"
  5: 	"fmt"
  6: 	"io"
  7: 	"os"
  8: )
  9: 
 10: func main() {
 11: 	//只讀的方式開啟
 12: 	inputFile, err := os.Open("input.dat")
 13: 	if err != nil {
 14: 		fmt.Printf("open file err:%v\n", err)
 15: 		return
 16: 	}
 17: 	defer inputFile.Close()
 18: }

讀檔案

file.Read和file.ReadAt.

讀到檔案末尾返回:io.EOF

讀出整個檔案程式碼示例

  1: package main
  2: 
  3: import (
  4: 	"fmt"
  5: 	"io"
  6: 	"os"
  7: )
  8: 
  9: func main() {
 10: 	//只讀的方式開啟
 11: 	inputFile, err := os.Open(`D:\project\goland\files\wenjianduxie.go`)
 12: 	//如果你檔案在GOPath裡面,可以用下面的路徑
 13: 	//inputFile, err := os.Open("./wenjianduxie.go")
 14: 	if err != nil {
 15: 		fmt.Printf("err=%v\n", err)
 16: 		return
 17: 	}
 18: 	defer func() {
 19: 		err := inputFile.Close()
 20: 		if err != nil {
 21: 			fmt.Println("err1=", err)
 22: 		}
 23: 	}()
 24: 	var buf [128]byte
 25: 	var content []byte
 26: 	for {
 27: 		n, err := inputFile.Read(buf[:])
 28: 		if err == io.EOF {
 29: 			// 代表檔案讀完了
 30: 			break
 31: 		}
 32: 		if err != nil {
 33: 			fmt.Println("err=", err)
 34: 		}
 35: 		fmt.Println("length:", n)
 36: 		// 將一個切片追加到另一個切片
 37: 		content = append(content, buf[:n]...)
 38: 		fmt.Println("data:\n", string(content))
 39: 	}
 40: }

bufio原理

由於檔案讀寫相對記憶體讀寫效能較差,所以在讀大檔案時需要新增一層緩衝區,這就是bufio。
缺點:可能會丟失快取的資料

  1: func main() {
  2: 	inputFile, err := os.Open("input.dat")
  3: 	if err != nil {
  4: 		fmt.Println("err=", err)
  5: 		return
  6: 	}
  7: 
  8: 	defer inputFile.Close()
  9: 	inputReader := bufio.NewReader(inputFile)
 10: 	for {
 11: 		// 以換行符為分隔,一行一行打印出來。
 12: 		inputString, readerError :=inputReader.ReadString("\n")
 13: 		if readerError == io.EOF {
 14: 			return 
 15: 		}
 16: 		fmt.Printf("The input was : %s", inputString)
 17: 	}
 18: }

ioutil直接讀取整個檔案

  1: func main() {
  2: 	inputFile := "products.txt"
  3: 	outputFile := "products_copy.txt"
  4: 	buf, err := ioutil.ReadFile(inputFile)
  5: 	if err != nil{
  6: 		fmt.Fprintf(os.Stderr, "File Error:%s\n", err)
  7: 		return
  8: 	}
  9: 	fmt.Printf("%s\n", string(buf))
 10: }

讀取gzip壓縮檔案

  1: func main() {
  2: 	zipfile := "Myfile.gz"
  3: 	//open裡面也可以寫路徑
  4: 	fi, err1 := os.Open(zipfile)
  5: 	if err1 != nil {
  6: 		fmt.Fprintf(os.Stderr, "File Error:%s\n", err1)
  7: 		os.Exit(1)
  8: 	}
  9: 	fz, err2 := gzip.NewReader(fi)
 10: 	if err2 != nil {
 11: 		fmt.Fprintf(os.Stderr,"File Error:%s\n", err2)
 12: 		return
 13: 	}
 14: 	var r *bufio.Reader
 15: 	r = bufio.NewReader(fz)
 16: 	for {
 17: 		line, err := r.ReadString('\n')
 18: 		if err != nil {
 19: 			fmt.Println(“Done reading file”)
 20: 			os.Exit(0)
 21: 		}
 22: 		fmt.Println(line)
 23: 	}
 24: }

2.檔案寫入

os.OpenFile("檔名",檔案開啟模式,許可權控制)
檔案開啟模式:
1. os.O_WRONLY 只寫
2. os.O_CREATE 建立檔案
3. os.O_RDONLY 只讀
4. os.O_RDWR  讀寫
5. os.O_TRUNC 清空
6. OS.O_APPEND 追加
ps:可以這樣寫: os.O_WRONLY|os.O_CREATE,順序從左到右
許可權控制:
r --> 004
w --> 002
x –> 001

api

  1: file.Write()
  2: file.WriteAt()
  3: file.WriteString()

bufio檔案寫入快取區

  1: writer := bufio.NewWriter() // 開闢快取區
  2: writer.WriteString() // 寫入快取區
  3: writer.Flush() // 重新整理,從快取區寫入檔案

ioutil寫入整個檔案

  1: inputFile := "舊檔案"
  2: outputFile := "寫入的新檔案"
  3: buf, err := ioutil.ReadFile(inputFile)
  4: err = ioutil.WriteFile(outputFile, buf, 0x644)

3.defer原理圖示

執行順序從上到下

                 {返回值=x}
return x --
                 {RET指令}

                   {返回值=x}   
defer原理 -- {執行defer語句}
                   {RET指令}