作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
目录
- 一.文件的读取操作
- 1.什么是文件
- 2.IO流类型概述
- 3.文件的基本操作
- 3.1 打开和关闭文件
- 3.2 带缓冲大小读取文件内容
- 3.3 循环读取
- 4.ioutil包一次性读取小文件
- 4.1 ioutil包概述
- 4.2 ioutil读取整个文件
- 5.bufio包按行读取文件
- 二.文件的写入操作
- 1.文件的打开模式
- 2.Write和WriteString
- 3.bufio.NewWriter写入文件
- 4.WriteFile
- 三.文件的复制操作
- 1.拷贝文件内容案例
- 2.借助
io.Copy()
实现一个拷贝文件函数
一.文件的读取操作
1.什么是文件
计算机中的文件是存储在外部介质(通常是磁盘)上的数据集合,文件分为文本文件和二进制文件。文件是保存数据的地方,是数据源的一种,比如大家经常使用的word文件,txt文件,Excel,jpg,png,mp3,mp4,rmvb等都是文件。文件最主要的做哟合格就是保存数据,它既可以保存一张图片,也可以保存视频,声音等等。
2.IO流类型概述
如上图所示,IO(Input/Output)流是程序和数据源沟通的桥梁,IO流分为输入流和输出流两个不同的方向。输入流一般指的是程序读取源文件的场景。输出流一般指的是程序写入数据到目标文件的场景。
3.文件的基本操作
3.1 打开和关闭文件
package mainimport ("fmt""os"
)func main() {// 1.打开文件file, err := os.Open("/etc/hosts")if err != nil {fmt.Printf("打开文件出错, err= %v\n", err)}// 2.在程序退出前一定要关闭文件以释放资源defer file.Close()// 3.打开文件若没错,则可以对文件进行一系列的操作fmt.Printf("文件对象: %v\n", file)
}
3.2 带缓冲大小读取文件内容
package mainimport ("fmt""io""os"
)func main() {// 只读方式打开当前目录下的hosts文件file, err := os.Open("/etc/hosts")if err != nil {fmt.Println("打开文件失败!, err = ", err)return}// 为了防止文件忘记关闭导致内存泄漏,我们通常使用defer注册文件关闭语句。defer file.Close()// 定义一个缓冲区的字节切片,此处咱们可以一次性读取4096个字节大小数据区域。var cache = make([]byte, 4096)/*使用Read方法读取数据,需要专递一个字节切片,该切片大小表示一次性读取的文件内容的大小。- 1.当我们传递的字节切片大小较小时,尽管没有读取完文件的所有内容,也不会读取超出的内容哟。- 2、当我们传递的字节切片大小较大时,会将文件的内容全部读取出来,并不会重复读取文件的内容哟~*/n, err := file.Read(cache)if err == io.EOF {fmt.Println("文件读完了")return}if err != nil {fmt.Println("read file failed, err:", err)return}fmt.Printf("读取了%d字节数据\n", n)fmt.Printf("文件内容:\n%s", string(cache[:n]))
}
3.3 循环读取
package mainimport ("fmt""io""os"
)func main() {file, err := os.Open("/etc/hosts")if err != nil {fmt.Println("open file failed!, err:", err)return}defer file.Close()var content []bytevar tmp = make([]byte, 128)// 使用for循环读取文件中的所有数据。for {// 一次性读取的128字节的大小buf, err := file.Read(tmp)if err == io.EOF {fmt.Println("文件读完了")break}if err != nil {fmt.Println("文件读取失败,错误:", err)return}// 每次读取buf大小后都追加到content切片中content = append(content, tmp[:buf]...)}// 将所有的内容读取到content切片后,再统一打印fmt.Printf("文件内容:\n%s", string(content))
}
4.ioutil包一次性读取小文件
4.1 ioutil包概述
读取文件的内容并显示在终端(使用ioutil一次性将整个文件读入到内存中),这种方式适用于文件不大的情况。相关方法的函数有"ioutil.ReadFile"。
4.2 ioutil读取整个文件
package mainimport ("fmt""io/ioutil"
)func main() {// "io/ioutil"包的ReadFile方法能够读取完整的文件,只需要将文件名作为参数传入。content, err := ioutil.ReadFile("/etc/hosts")if err != nil {fmt.Println("读取文件出错, err:", err)return}// 读取文件的内容并显示在终端(使用ioutil一次性将整个文件读入到内存中),这种方式适用于文件不大的情况。fmt.Printf("文件内容: \n%v", string(content))
}
5.bufio包按行读取文件
package mainimport ("bufio""fmt""io""os"
)func main() {// 打开文件file, err := os.Open("/etc/hosts")if err != nil {fmt.Println("文件打开失败, err=", err)return}// 当函数退出是,让file关闭,防止内存泄漏;defer file.Close()// 创建一个IO流,bufio是在file的基础上封装了一层API,支持更多的功能。reader := bufio.NewReader(file)// 读取操作for {// 按行读取,注意是字符'\n'。line, err := reader.ReadString('\n')// 表示已经读取到文件的结尾if err == io.EOF {if len(line) != 0 {fmt.Println(line)}fmt.Println("文件读完了")break}if err != nil {fmt.Println("读取文件失败, err:", err)return}// 如果没有读取到文件结尾的话,就正常输出文件内容即可。fmt.Print(line)}//fmt.Println("文件读取成功,程序运行结束...")
}
二.文件的写入操作
1.文件的打开模式
模式 | 含义 |
---|---|
os.O_RDONLY |
只读模式打开文件 |
os.O_WRONLY |
只写模式打开文件 |
os.O_RDWR |
读写模式打开文件 |
os.O_APPEND |
写操作时将数据附加到文件尾部 |
os.O_CREATE |
创建文件 |
os.EXCL |
和os.OCREATE 配合使用,文件必须不存在 |
os.SYNC |
打开文件用于同步I/O |
os.O_TRUNC |
如果文件存在,则打开文件时先清空再打开 |
os.OpenFile()函数能够以指定模式打开文件,从而实现文件写入相关功能。func OpenFile(name string, flag int, perm FileMode) (*File, error) {...}相关参数说明:- name:要打开的文件名 - flag:打开文件的模式,常见的模式如上表所示。- perm:文件权限,一个八进制数。r(读)04,w(写)02,x(执行)01。
2.Write和WriteString
package mainimport ("fmt""os"
)func main() {// 以只写的模式打开文件file, err := os.OpenFile("blog.txt", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)if err != nil {fmt.Println("文件打开失败, err= ", err)return}defer file.Close()str := "博客地址: https://www.cnblogs.com/yinzhengjie\n\n"//写入字节切片数据file.Write([]byte(str))//直接写入字符串数据file.WriteString("Go视频教学地址: https://www.bilibili.com/video/BV1bwhve7EPJ/\n")}
3.bufio.NewWriter写入文件
package mainimport ("bufio""fmt""os"
)func main() {// 以只写的模式打开文件file, err := os.OpenFile("./yinzhengjie.log", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)// 判断文件是否打开失败if err != nil {fmt.Println("open file failed, err:", err)return}// 及时将文件关闭,防止内存泄漏defer file.Close()// 写入操作,获取一个IO流,带缓冲区的输出流writer := bufio.NewWriter(file)// 将数据写入缓冲区for i := 0; i < 10; i++ {writer.WriteString("博客地址: https://www.cnblogs.com/yinzhengjie\n")}// 将缓冲区的数据刷新到磁盘writer.Flush()// tips: 查看文件打开模式,需要懂Linux基础知识mode := os.FileMode(0644).String()fmt.Printf("mode: 0644 = %s\n", mode)}
4.WriteFile
package mainimport ("fmt""io/ioutil"
)func main() {str := "{\"尹正杰博客地址\": \"https://www.cnblogs.com/yinzhengjie\"}"// ioutil.WriteFile写入文件时,若文件已存在或者有内容,会直接将源文件清空哟~err := ioutil.WriteFile("./blog.json", []byte(str), 0666)if err != nil {fmt.Println("文件打开失败,错误 = ", err)return}}
三.文件的复制操作
1.拷贝文件内容案例
package mainimport ("fmt""io/ioutil"
)func main() {// 1.定义需要拷贝的源文件srcFile := "/etc/hosts"// 2.定义拷贝到目标文件路径destFile := "./hosts"// 3.对源文件进行读取数据content, err := ioutil.ReadFile(srcFile)if err != nil {fmt.Printf("文件读取失败: err = %s\n", err)return}// 4.将读取到的数据写入目标文件err = ioutil.WriteFile(destFile, content, 0644)if err != nil {fmt.Printf("文件写入失败, err=%v\n", err)}fmt.Printf("'%s'文件拷贝完成\n", srcFile)
}
2.借助io.Copy()
实现一个拷贝文件函数
package mainimport ("fmt""io""os"
)// CopyFile 拷贝文件函数
func CopyFile(dstFile, srcFile string) (written int64, err error) {// 以读方式打开源文件src, err := os.Open(srcFile)if err != nil {fmt.Printf("打开%s文件失败, err = %v\n", srcFile, err)return}defer src.Close()// 以写|创建的方式打开目标文件dest, err := os.OpenFile(dstFile, os.O_WRONLY|os.O_CREATE, 0644)if err != nil {fmt.Printf("打开%s文件失败, err = %v\n", dstFile, err)return}defer dest.Close()//调用io.Copy()拷贝内容文件内容return io.Copy(dest, src)
}func main() {_, err := CopyFile("./hosts", "/etc/hosts")if err != nil {fmt.Println("拷贝文件失败,err = ", err)return}fmt.Println("拷贝完成")
}