[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   进击的davis  阅读(881)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性

导航

< 2025年2月 >
26 27 28 29 30 31 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 1
2 3 4 5 6 7 8
点击右上角即可分享
微信分享提示