golang读取文件总结

作者: adm 分类: go 发布时间: 2023-03-29

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()
}

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!