20 Go 文件IO (一):文件操作
一、文件处理概述
基本所有语言都支持一些文件资源的IO操作,所谓IO即对资源的读写。在类Unix的设计哲学中,一切资源皆为文件。在IO中你会常见到一些Write、Read、Writer、Reader的概念,有时你会对一些读写主体产生混淆,这里可以明晰一下:
一般读写的主体都为运行的程序,程序运行于内存中,而资源一般位于程序主体的外部,多以Read一般理解为读入,将外部资源读入程序内存,而Write则相反,指数据有程序内存写出到外部的磁盘资源。当然所谓外部不一定指磁盘,这里的外部是相对程序主体而言的。而Reader、Writer就好理解了,它们是抽象化的读写操作主体,如Read操作是通过Reader实现的,Reader内部提供Read方法。另外,IO操作的数据单位一般都为byte,你会看到go的标准库中,许多数据IO都是通过[]byte传输的。
理清以上比较容易混淆的概念再去阅读Go的IO相关包源码就好理解了。
二、Go IO标准包
- os包
一个平台无关的操作系统接口,提供一些系统资源的调用功能,如文件、目录打开关闭,环境设置、状态信息等。
- io包
提供了对I/O原语的基本接口。本包的基本任务是包装这些原语已有的实现(如os包里的原语),使之成为共享的公共接口,这些公共接口抽象出了泛用的函数并附加了一些相关的原语的操作。与os包配合,所谓io就是一些读写的操作。
- io/ioutil包
基于io包实现一些实用的工具函数,由于封装性较好,使用简单,所以日常开发该包使用多一些。
- bufio包
bufio包实现了有缓冲的I/O。它包装一个io.Reader或io.Writer接口对象,创建另一个也实现了该接口,且同时还提供了缓冲和一些文本I/O的帮助函数的对象。如操作的资源较大,一般建议使用带缓冲的bufio。
三、文件操作演示
1.基本文件读写
示例一:打开一个文件简单操作,打开后延时关闭。
func BaseFileOperation01() {
file, err := os.Open("/path/to/file_operation_demo_text.txt")
if err != nil {
fmt.Println("文件打开错误,err=", err)
return
}
//完成后延时1s关闭
defer func() {
time.Sleep(time.Second)
file.Close()
}()
info, _ := file.Stat()
fmt.Println(info.Name())
}
示例二:以只读方式打开一个文件创建缓冲读取器,逐行读到末尾。
func BaseFileOperation02() {
file, err := os.OpenFile("/path/to/file_operation_demo_text.txt", os.O_RDONLY, 0666)
if err != nil {
fmt.Println("文件打开错误,err=", err)
return
}
defer file.Close() //完成后关闭
//创建缓冲读取器
reader := bufio.NewReader(file)
for {
readString, err := reader.ReadString('\n') //以换行符为间隔分箱读取
if err != nil {
if e == io.EOF {
break
}
fmt.Println("缓冲读取错误,err=", err)
return
}
fmt.Println(readString)
}
fmt.Println("缓冲读取文件完成")
}
示例三:使用ioutil包对文件进行简易读取
func BaseFileOperation03() {
bytes, err := ioutil.ReadFile("/path/to/file_operation_demo_text.txt")
if err != nil {
fmt.Println("文件打开错误,err=", err)
return
}
fmt.Println(string(bytes))
}
示例四:以创写追加或创写覆盖方式打开一个文件,缓冲式写出几行数据,倒干缓冲区后退出
func BaseFileOperation04() {
openFile, err := os.OpenFile("/path/to/file_operation_demo_text111.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if e != nil {
fmt.Println("文件打开错误,err=", err)
return
}
defer openFile.Close()
//创建一个缓冲桶
writer := bufio.NewWriter(openFile)
writer.WriteString("这是新插入的信息1\n")
writer.WriteString("这是新插入的信息2\n")
writer.WriteString("这是新插入的信息3\n")
writer.WriteString("这是新插入的信息4\n")
flush := writer.Flush()
fmt.Println("缓冲写入数据完成!!!清空缓冲状态:", flush)
}
示例五:使用os包的状态检测结合os.IsNotExist(err)判断文件是否存在。
func BaseFileOperation05() {
_, err := os.Open("/path/to/file_operation_demo_text11.txt")
exist1 := os.IsNotExist(err)
fmt.Println("文件是否不存在:", exist1)
exist2 := os.IsExist(err)
fmt.Println("文件是否存在:", exist2)
}
示例六:使用ioutil包进行建议文件写出。
func BaseFileOperation06() {
//
stringByte := []byte("这是一次用ioutil包的简易写出操作\n")
ioutil.WriteFile("/path/to/file_operation_demo_text111.txt", stringByte, 0666)
fmt.Println("简易写出完成!")
}
2.文件拷贝
示例七:ioutil包简单拷贝
func BaseFileOperation07() {
bytes, err := ioutil.ReadFile("/path/to/file_operation_demo_text111.txt")
if e != nil {
fmt.Println("文件读取错误,err=", err)
return
}
err = ioutil.WriteFile("/path/to/file_operation_demo_text222.txt", bytes, 0666)
if err != nil {
fmt.Println("文件写入错误,err=", err)
return
}
fmt.Println("文件拷贝完成!!!")
}
示例八:io.Copy进行文件拷贝
func BaseFileOperation08() {
//只读模式打开文件
src, err := os.OpenFile("/path/to/file_operation_demo_text.txt", os.O_RDONLY, 0666)
if err != nil {
fmt.Println("文件打开错误,err=", err)
return
}
defer src.Close()
//只写模式打开创建文件
dst, err := os.OpenFile("/Users/fun/Code/mygo/src/mydemo/text/file_operation_demo_text_copy.txt", os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
fmt.Println("文件写入错误,err=", err)
return
}
defer dst.Close()
written, err := io.Copy(dst, src)
if err != nil {
fmt.Println("ioutil拷贝操作错误!!!")
return
}
fmt.Println("ioutil拷贝操作完成:", written)
}
示例九:使用缓冲1K的缓冲区配合缓冲读写器进行图片拷贝
func BaseFileOperation09() {
src, err := os.OpenFile("/path/to/myimage.jpg", os.O_RDONLY, 0666)
if err != nil {
fmt.Println("文件打开错误,err=", err)
return
}
defer src.Close()
//只写模式打开创建文件
dst, err := os.OpenFile("/path/to/myimage_copy.jpg", os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
fmt.Println("文件写入错误,err=", err)
return
}
defer dst.Close()
//创建缓冲区[[byte
var n int = 0
bufbytes := make([]byte, 1024)
reader := bufio.NewReader(src)
writer := bufio.NewWriter(dst)
for {
n++
_, err = reader.Read(bufbytes)
if err != nil {
if err == io.EOF {
fmt.Println("文件读到末尾!", n)
break
}
fmt.Println("读取图片到缓冲区错误:", err)
}
_, err = writer.Write(bufbytes)
if err != nil {
fmt.Println("读取图片到缓冲区错误:", err)
}
}
}