[go-每日一库] golang通过io/bufio库实现文件的读写及解封包操作

在日常操作中,对文件的操作比较多的是打开文件、关闭文件、读取内容、写入内容、打包、解包,今天分享个这些操作的基本case,用到的库也都是go自带的常用库,包括io、bufio、archive/zip等。

本文用到库的import:

import (
	"archive/zip"
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"strings"
)

go官方提供的io,bufio库对文件进行相关操作

  • 1.io库直接操作文件
  • 2.bufio提供缓冲区操作文件

1.文件的基本操作-创建、打开、关闭、权限

直接上代码:

func main()  {
	// 1.文件的基础操作,create/open/close/chmod -> go/io库
	// 创建文件 create file
	f, err := os.Create("create.txt")
	if err != nil {
		log.Fatalf("get file info error: %s\n", err.Error())
	}
	// 文件状态信息 file stats
	fileInfo, err := f.Stat()
	if err != nil {
		log.Fatalf("create file error: %s\n", err.Error())
	}
	log.Printf("File Name is %s\n", fileInfo.Name())
	log.Printf("File Permissions is %s\n", fileInfo.Mode())
	log.Printf("File ModTime is %s\n", fileInfo.ModTime())

	// 文件权限 chmod
	err = f.Chmod(0777)
	if err != nil {
		log.Fatalf("chmod file failed err=%s\n", err.Error())
	}
	// 文件属者 chown, windows os 除外
	err = f.Chown(os.Getuid(), os.Getgid())
	if err != nil{
		log.Fatalf("chown file failed err=%s\n", err)
	}

	// 确认文件属性修改成功
	fileInfo, err = f.Stat()
	if err != nil{
		log.Fatalf("get file info second failed err=%s\n", err)
	}
	log.Printf("File change Permissions is %s\n", fileInfo.Mode())

	// 关闭文件 close
	err = f.Close()
	if err != nil{
		log.Fatalf("close file failed err=%s\n", err)
	}
	// 删除文件 delete
	err = os.Remove("create.txt")
	if err != nil{
		log.Fatalf("remove file failed err=%s\n", err)
	}
}

2.文件的写入

直接上代码:

func main()  {

	// 1.快写文件 fast write file -> os/ioutil, 封装openFile/write/close,一条龙服务
	err := os.WriteFile("fastwrite.txt", []byte("Hi fast write\n"), 0666)
	if err != nil {
		log.Fatalf("fast write failed, err=%s\n", err.Error())
	}

	// 2.按行写入文件, os、bufio没有直接提供按行写入,故调用os.WriteString、bufio.WriteString方法,再加入换行符
	// 2.1 直接操作io
	data := []string{
		"demo",
		"test",
		"123",
	}
	f, err := os.OpenFile("directIO.txt", os.O_CREATE|os.O_WRONLY, 0666)
	if err != nil {
		log.Fatalf("open file failed, err=%s\n", err.Error())
	}
	// 写入数据
	for _, line := range data {
		_, err = f.WriteString(line + "\n")
		if err != nil {
			log.Fatalf("write one line data failed, err=%s\n", err.Error())
		}
	}
	_ = f.Close()


	// 2.2 缓冲区写入 buffer IO
	file, err := os.OpenFile("bufIO.txt", os.O_CREATE|os.O_WRONLY, 0666)
	if err != nil {
		log.Fatal(err.Error())
	}
	// create file buf writer
	bufWriter := bufio.NewWriter(file)
	for i := 0; i < 3; i++ {
		// 写入string到buffer
		bytesWritten, err := bufWriter.WriteString("you are awesome\n")
		if err != nil {
			log.Fatal(err.Error())
		}
		log.Printf("Bytes written: %d\n", bytesWritten)
	}
	// write memory to disk
	err = bufWriter.Flush()
	if err != nil {
		log.Fatal(err.Error())
	}
	_ = file.Close()


	// 3.偏移量offset写入
	data1 := []byte{
		0x41, // A
		0x73, // s
		0x20, // space
		0x20, // space
		0x67, // g
	}
	f, err = os.OpenFile("offset.txt", os.O_CREATE|os.O_WRONLY, 0666)
	if err != nil {
		log.Println(err.Error())
	}
	// 先写入数据
	_, err = f.Write(data1)
	replace := []byte{
		0x6F, // o
		0x6E, // n
	}
	_, err = f.WriteAt(replace, 2)
	if err != nil {
		log.Println(err.Error())
	}
	_ = f.Close()



	// 4.write with buffer
	// io直写是方便,同样如果频繁操作的话,会增加CPU的中断频率,可以通过内存缓冲区减少IO操作,即buffer io 写入
	// user program -> memory(buffer) -> disk
	f, err = os.OpenFile("bufferWrite.txt", os.O_CREATE|os.O_WRONLY, 0666)
	if err != nil {
		log.Println(err.Error())
	}
	// create buf writer
	buf := bufio.NewWriter(f) // size=4096 0r 4k
	// write string to buffer
	bytesWritten, err := buf.WriteString("bufferio write\n")
	if err != nil {
		log.Println(err)
	}
	log.Printf("bytes written: %d\n", bytesWritten)
	// check buffer bytes count
	unflushedBufSize := buf.Buffered()
	log.Printf("bytes buffered: %d\n", unflushedBufSize)
	// 未使用的缓存的大小,check remain bytes which can use
	bytesAvailable := buf.Available()
	log.Printf("Available buffer: %d\n", bytesAvailable)
	// 刷盘
	_ = buf.Flush()
	// close file
	_ = f.Close()

}

3.读取文件

func main()  {

	// 3.1 读取全文
	// os.readFile
	data, err := os.ReadFile("bufIO.txt")
	if err != nil {
		log.Println(err.Error())
	}
	log.Println("read %s content is %s\n", "bufIO.txt", string(data))
	// ioutil.readall
	file, err := os.Open("bufIO.txt")
	if err != nil {
		log.Println(err)
	}
	content, err := ioutil.ReadAll(file)
	log.Printf("read %s content is %s\n", "bufIO.txt", content)

	file.Close()


	// 3.2 read by line
	// os.read -> read by bytes length
	// bufio.readLine/readBytes/readString -> read by line
	file, err = os.OpenFile("bufIO.txt", os.O_RDONLY, 0666)
	if err != nil {
		log.Println(err.Error())
	}
	bufReader := bufio.NewReader(file)
	// read by line, use for-loop
	for {
		linBytes, err := bufReader.ReadBytes('\n')
		//bufReader.ReadLine() // low level use
		line := strings.TrimSpace(string(linBytes))
		if err != nil && err != io.EOF {
			log.Println(err.Error())
		}
		if err == io.EOF {
			break
		}
		log.Printf("readline %s every line data is %s\n", "bufIO.txt", line)
	}
	_ = file.Close()



	// 3.3 read file by block
	// os库的Read方法
	// os库配合bufio.NewReader调用Read方法
	// os库配合io库的ReadFull、ReadAtLeast方法
	// bufio.NewReader
	file, err = os.OpenFile("bufIO.txt", os.O_RDONLY, 0666)
	if err != nil {
		log.Println(err)
	}
	// create reader
	r := bufio.NewReader(file)
	// read 2 bytes every time
	buf := make([]byte, 2)
	for {
		n, err := r.Read(buf)
		if err != nil && err != io.EOF {
			log.Println(err.Error())
		}
		if n == 0 {
			break
		}
		log.Printf("readByte %s every read 2 byte is %s\n", "bufIO.txt", string(buf[:n]))
	}
	_ = file.Close()


	// os.read
	file, err = os.OpenFile("bufIO.txt", os.O_RDONLY, 0666)
	if err != nil {
		log.Println(err.Error())
	}
	buf = make([]byte, 2)
	for {
		n, err := file.Read(buf)
		if err != nil && err != io.EOF {
			log.Println(err.Error())
		}
		if n == 0 {
			break
		}
		log.Printf("readByte %s every read 2 byte is %s\n", "bufIO.txt", string(buf[:n]))
	}
	_ = file.Close()



	// io.ReadAtLeast()
	file, err = os.OpenFile("bufIO.txt", os.O_RDONLY, 0666)
	if err != nil {
		log.Println(err.Error())
	}
	buf = make([]byte, 2)
	for {
		n, err := io.ReadAtLeast(file, buf, 1)
		if err != nil && err != io.EOF {
			log.Println(err.Error())
		}
		if n == 0 {
			break
		}
		log.Printf("readByte %s every read 2 byte is %s\n", "bufIO.txt", string(buf[:n]))
	}
	_ = file.Close()
}

4.打包、解包

func main()  {
	// zip 解包
	// open a zip archive for reading
	r, err := zip.OpenReader("txt.zip")
	if err != nil {
		log.Println(err)
	}
	defer r.Close()
	// iterate through files in the archive && print their contents
	for _, f := range r.File {
		fmt.Printf("content of %s:\n", f.Name)
		rc, err := f.Open()
		if err != nil {
			log.Println(err.Error())
		}
		_, err = io.CopyN(os.Stdout, rc, 68)
		if err != nil {
			log.Println(err.Error())
		}
		rc.Close()
	}

	// zip 打包
	// create a archive
	zipFile, err := os.Create("out.zip")
	if err != nil {
		log.Println(err.Error())
	}
	// create new zip archive
	w := zip.NewWriter(zipFile)
	// add some file to the archive
	var files = []struct{
		Name, Body string
	}{
		{"asong.txt", "This archive contains some text files."},
		{"todo.txt", "Get animal handling licence.\nWrite more examples."},
	}
	for _, file := range files {
		// create file
		f, err := w.Create(file.Name)
		if err != nil {
			log.Println(err.Error())
		}
		// write content
		_, err = f.Write([]byte(file.Body))
		if err != nil {
			log.Println(err.Error())
		}
	}
	// check error on close
	err = w.Close()
	if err != nil {
		log.Println(err.Error())
	}
}

参考文档:

posted on 2022-07-16 14:47  进击的davis  阅读(621)  评论(0编辑  收藏  举报

导航