golang中的标准库IO操作
输入输出的底层原理
终端其实是一个文件,相关实例如下:
- os.Stdin:标准输入的文件实例,类型为*File
- os.Stdout:标准输出的文件实例,类型为*File
- os.Stderr:标准错误输出的文件实例,类型为*File
以文件的方式操作终端:
func main() {
var buf [16]byte
os.Stdin.Read(buf[:])
fmt.Println(string(buf[:])) }
文件操作相关API
- func Create(name string) (file *File, err Error)
根据提供的文件名创建新的文件,返回一个文件对象,默认权限是0666 - func NewFile(fd uintptr, name string) *File 根据文件描述符创建相应的文件,返回一个文件对象
- func Open(name string) (file *File, err Error) 只读方式打开一个名称为name的文件 案例:
func main() {
file, _ := os.Open("./log/2021-11-29.txt") // 以只读方式打开文件
fileInfo, _ := file.Stat() // 获取文件信息
fileSize := fileInfo.Size() // 获取文件字节大小
buf := make([]byte, fileSize) // 创建一个buf变量
file.Read(buf) // 将文件内容读取到buf中
fmt.Println(string(buf)) // 输出 }
输出结果:
2021/11/29 16:52:35.242112 C:/Users/mayanan/Desktop/pro_go/common_standard_library/main.go:20: 这是一条很普通的日志。
[小王子]2021/11/29 16:52:35.242721 C:/Users/mayanan/Desktop/pro_go/common_standard_library/main.go:22: 这是一条很普通的日志。
- func OpenFile(name string, flag int, perm uint32) (file *File, err Error) 打开名称为name的文件,flag是打开的方式,只读、读写等,perm是权限
- func (file *File) Write(b []byte) (n int, err Error) 写入byte类型的信息到文件
- func (file *File) WriteString(s string) (ret int, err Error) 写入string信息到文件
- 案例:
func main() {
file, _ := os.OpenFile("./log/2021-11-29.txt", os.O_APPEND, 0644)
file.Write([]byte("哈哈哈\n")) file.WriteString("你好啊\n") }
- func (file *File) WriteAt(b []byte, off int64) (n int, err Error) 在指定位置开始写入byte类型的信息
案例:
func main() {
// If file was opened with the O_APPEND flag, WriteAt returns an error.
file, _ := os.OpenFile("./log/2021-11-29.txt", os.O_WRONLY, 0644)
file.WriteAt([]byte("你好啊\n"), 15) }
- func Remove(name string) Error 删除文件名为name的文件
func main() {
os.Remove("./log/2021-11-29.txt") // 删除一个文件
os.RemoveAll("./log/") // 删除目录及目录下的所有文件 }
打开和关闭文件
os.Open()函数能够打开一个文件,返回一个*File和一个err。对得到的文件实例调用close()方法能够关闭文件。
package main
import ( "fmt" "os" )
func main() {
// 只读方式打开当前目录下的main.go文件
file, err := os.Open("./main.go")
if err != nil {
fmt.Println("open file failed!, err:", err)
return
} // 关闭文件 file.Close() }
写文件
package main
import ( "fmt" "os" )
func main() {
// 新建文件
file, err := os.Create("./xxx.txt") if err != nil {
fmt.Println(err) return
}
defer file.Close()
for i := 0; i < 5; i++ {
file.WriteString("ab\n")
file.Write([]byte("cd\n"))
}
}
读文件
文件读取可以用file.Read()和file.ReadAt(),读到文件末尾会返回io.EOF的错误
func main() {
// 打开文件
file, err := os.Open("./test/t01.txt") if err != nil { fmt.Println("open file failed")
return }
defer file.Close()
// 定义接收文件读取的字节数组
var content []byte
var buf [128]byte
for {
n, err := file.Read(buf[:])
if err == io.EOF {
// 读取结束 break
}
if err != nil {
fmt.Println("Read failed")
return
}
content = append(content, buf[:n]...)
}
fmt.Println(string(content)) }
拷贝文件(单个 main goroutine)
func main() {
//c := make(chan []byte, 1024)
//wg.Add(1)
//ReadFile(c)
//wg.Add(1)
//go WriteFile(c)
//wg.Wait()
// 删除副本
os.Remove("./test/t01副本.txt") file, _ := os.Open("./test/t01.txt")
buf := make([]byte, 10)
for {
n, err := file.Read(buf)
if err == io.EOF {
fmt.Println("读取完毕")
break
}
if err != nil {
fmt.Println("读取失败")
return
}
fmt.Println(string(buf))
newFile, _ := os.OpenFile("./test/t01副本.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
newFile.Write(buf[:n])
}
}
拷贝文件(两个goroutine,一个读,一个写)
并且:读、写采用异步通道
var wg sync.WaitGroup
func main() {
// c通道用来传输数据 c := make(chan []byte, 1024)
// 此处使用异步通道
// 还需要一个通道用来传输每次写入到通道的字节个数
bc := make(chan int, 1024) // 1024代表通道的容量
wg.Add(1)
go ReadFile(c, bc)
wg.Add(1)
go WriteFile(c, bc)
wg.Wait()
}
func ReadFile(c chan []byte, bc chan int) {
defer wg.Done()
file, err := os.Open("./test/t01.txt") if err != nil { fmt.Println("Open file failed")
return
}
defer file.Close()
for {
// 注意:定义buf一定要放在for循环里面 // 如果放在循环外面,buf只保存最后一次file.Read(buf)的数据,就会出现bug var buf = make([]byte, 10) // 每次读取10个字节的数据放入到通道中
n, err := file.Read(buf)
if err == io.EOF {
fmt.Println("读取完毕")
close(c) // 关闭通道
close(bc)
return
}
if err != nil {
fmt.Println("Read file failed")
return
}
bufio
- bufio包实现了带缓冲区的读写,是对文件读写的封装
- bufio缓冲写数据
模式 | 含义 |
---|---|
os.O_WRONLY | 只写 |
os.O_CREATE | 创建文件 |
os.O_RDONLY | 只读 |
os.O_RDWR | 读写 |
os.O_TRUNC | 清空 |
os.O_APPEND | 追加 |
- bufio读数据
func main() {
//wr()
re()
}
func re() {
// 读文件用os.Open
file, err := os.Open("./t01.txt")
if err != nil {
fmt.Println(err.Error())
return
}
defer file.Close()
// 获取reader对象
reader := bufio.NewReader(file)
for {
line, _, err := reader.ReadLine()
if err == io.EOF {
break
}
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println(string(line))
}
}
func wr() {
// 写文件用os.OpenFile
file, err := os.OpenFile("t01.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
fmt.Println(err.Error())
return
}
defer file.Close()
// 获取Writer对象
writer := bufio.NewWriter(file)
for i := 0; i < 10; i++ {
writer.WriteString(fmt.Sprintf("hello %d\n", i))
}
// 刷新缓冲区,强制写出
writer.Flush()
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)