1. 程式人生 > 其它 >golang讀取檔案總結

golang讀取檔案總結

1. 讀取整個檔案

讀取整個檔案是效率最高的一種方式,但其只適用於小檔案,大檔案一次讀取會消耗大量記憶體

1.1 使用檔名直接讀取

使用os.ReadFile()方法可以實現直接讀取

func fileOne() {
	content, err := os.ReadFile("test.txt")
	if err != nil {
		panic(err)
	}
	fmt.Println(string(content))
}

使用ioutil.ReadFile()方法可以實現一樣的效果,這兩個函式其實是完全一樣的

func fileTwo() {
	content, err := ioutil.ReadFile("test.txt")
	if err != nil {
		panic(err)
	}
	fmt.Println(string(content))
}

1.2 先建立檔案控制代碼再讀取檔案

如果想以只讀方式開啟檔案的話,可以直接使用os.Open()方法

func fileThree() {
	file, err := os.Open("test.txt")
	if err != nil {
		panic(err)
	}
	defer file.Close()

	content, err := ioutil.ReadAll(file)
	fmt.Println(string(content))
}

或者使用通用的os.OpenFile()方法,不過要多加兩個引數

func fileFour() {
	file, err := os.OpenFile("test.txt", os.O_RDONLY, 0)
	if err != nil {
		panic(err)
	}
	defer file.Close()

	content, err := ioutil.ReadAll(file)
	fmt.Println(string(content))
}

2. 按行讀取

按行讀取主要使用ioutil庫,其中有兩個方法可以實現按行讀取

但要注意的是,按行讀取是以'\n'來區分每一行的,如果是沒有分行的大檔案,就不能使用按行讀取了

使用ioutil.ReadBytes()實現按行讀取檔案

func fileFive() {
	// 建立檔案控制代碼
	fi, err := os.Open("test.txt")
	if err != nil {
		panic(err)
	}
	defer fi.Close()

	// 建立reader
	r := bufio.NewReader(fi)

	for {
		lineBytes, err := r.ReadBytes('\n')
		line := strings.TrimSpace(string(lineBytes))
		if err != nil && err != io.EOF {
			panic(err)
		}
		if err == io.EOF {
			break
		}
		fmt.Println(line)
	}
}

使用ioutil.ReadString()同樣可以實現按行讀取

func fileSix() {
	// 建立檔案控制代碼
	fi, err := os.Open("test.txt")
	if err != nil {
		panic(err)
	}
	defer fi.Close()

	// 建立reader
	r := bufio.NewReader(fi)

	for {
		line, err := r.ReadString('\n')
		line = strings.TrimSpace(line)
		if err != nil && err != io.EOF {
			panic(err)
		}
		if err == io.EOF {
			break
		}
		fmt.Println(line)
	}
}

3. 按位元組數讀取

對於不分行的大檔案來說,只能使用按位元組讀取來讀取整個檔案

按位元組讀取可以使用os庫或者syscall庫來實現

使用os庫實現按位元組讀取

func fileSeven() {
	// 建立檔案控制代碼
	fi, err := os.Open("test.txt")
	if err != nil {
		panic(err)
	}
	defer fi.Close()

	// 建立reader
	r := bufio.NewReader(fi)

	// 每次讀取1024個位元組
	buf := make([]byte, 1024)
	for {
		n, err := r.Read(buf)
		if err != nil && err != io.EOF {
			panic(err)
		}
		if n == 0 {
			break
		}
		fmt.Println(string(buf[:n]))
	}
}

使用syscall庫實現按位元組讀取

func fileEight() {
	fd, err := syscall.Open("test.txt", syscall.O_RDONLY, 0)
	if err != nil {
		fmt.Println("Failed on open: ", err)
	}
	defer syscall.Close(fd)

	var wg sync.WaitGroup
	wg.Add(2)
	dataChan := make(chan []byte)
	go func() {
		wg.Done()
		for {
			data := make([]byte, 100)
			n, _ := syscall.Read(fd, data)
			if n == 0 {
				break
			}
			dataChan <- data
		}
		close(dataChan)
	}()

	go func() {
		defer wg.Done()
		for {
			select {
			case data, ok := <-dataChan:
				if !ok {
					return
				}

				fmt.Println(string(data))
			default:
			}
		}
	}()

	wg.Wait()
}