文章目录
前言
介绍各类文件经常用来做什么工作,以及在Go语言中操作各类文件的方法
一、文件类型及作用?
①文件的职能作用
文件一般都有后缀名,根据他的后缀名区分文件的职能类型,比如jpg,png后缀结尾的是照片,txt结尾的是文本文件…
一般的文件大家都知道是用来干什么的就不进行详细阐述了,一下主要讲解一下大家可能不太了解的文件类型,
(1)json文件
JSON文件是用来存储简单的数据结构和对象的文件,可以在web应用程序中进行数据交换 JSON是全称为JavaScript Object Notation,是一种有条理,易于访问的存储信息的方法。 • 1 • 2
代码如下:
[{"Name":"Golang", "Url":"http://c.biancheng.net/golang/"," Course":["http://c.biancheng.net/cplus/","http://c.biancheng.net/linux_tutorial/"]}, {"Name":"Java", "Url":"http://c.biancheng.net/java/", "Course":["http://c.biancheng.net/socket/","http://c.biancheng.net/python/"]}]
(2)xml文件
可扩展标记语言,标准通用标记语言的子集,简称XML。 是一种用于标记电子文件使其具有结构性的标记语言。 一般存储映射关系,在javaweb中有应用web.xml在人工智能中也有应用,比如进行深度学习目标检测用到的数据集, 可以使用xml文件记录一种映射关系对需要训练的数据集进行标注。
代码如下:
<annotation> <folder>VOC2012</folder> <filename>2007_000027.jpg</filename> <source> <database>The VOC2007 Database</database> <annotation>PASCAL VOC2007</annotation> <image>flickr</image> </source> <size> <width>486</width> <height>500</height> <depth>3</depth> </size> <segmented>0</segmented> <object> <name>person</name> <pose>Unspecified</pose> <truncated>0</truncated> <difficult>0</difficult> <bndbox> <xmin>174</xmin> <ymin>101</ymin> <xmax>349</xmax> <ymax>351</ymax> </bndbox> <part> <name>head</name> <bndbox> <xmin>169</xmin> <ymin>104</ymin> <xmax>209</xmax> <ymax>146</ymax> </bndbox> </part> <part> <name>hand</name> <bndbox> <xmin>278</xmin> <ymin>210</ymin> <xmax>297</xmax> <ymax>233</ymax> </bndbox> </part> <part> <name>foot</name> <bndbox> <xmin>273</xmin> <ymin>333</ymin> <xmax>297</xmax> <ymax>354</ymax> </bndbox> </part> <part> <name>foot</name> <bndbox> <xmin>319</xmin> <ymin>307</ymin> <xmax>340</xmax> <ymax>326</ymax> </bndbox> </part> </object> </annotation>
(3)gob二进制文件
gob是 Go Binary的简写,是将go语言结构体进行序列化的一种方式,gob文件属于自描述文件,他里面包含所有类型的自描述 进行解码的时候不需要了解文件的内容,在编码解码过程中,零值会被忽略,在解码过程中只有只有匹配名称,和可兼容字段才会被 解码
注意:gob二进制文件比较安全,无法直接打开
②Go语言操作文件的注意点
(1)操作json文件时:
保持字段名大写,可以将对应的字段加入到json文件内
(2)操作xml文件:
结构体字段名后面可以跟类似 `xml:"Name,attr"`、`xml:"Url>Course"`的字符串,用来解释这个字段在xml中的层次结构 除了这两种还有'xml:",chardata"' 将本字段当作字符数据来写 'xml:",innerxml"' 将本字段按照字面量来写 'xml:",comment"' 改字段将作为xml注释,写进xml文件
③打开文件的权限
(1)打开文件使用的函数
func OpenFile(name string, flag int, perm FileMode) (file *File, err error) name为文件名,flag为打开文件权限方式
(2)flag的种类及作用
O_RDONLY:只读模式打开文件; O_WRONLY:只写模式打开文件; O_RDWR:读写模式打开文件; O_APPEND:写操作时将数据附加到文件尾部(追加); O_CREATE:如果不存在将创建一个新文件; O_EXCL:和 O_CREATE 配合使用,文件必须不存在,否则返回一个错误; O_SYNC:当进行一系列写操作时,每次都要等待上次的 I/O 操作完成再进行; O_TRUNC:如果可能,在打开时清空文件。
二、实战使用Go语言操作文件
1.操作json文件
①写文件
代码如下(示例):
package main import ( "encoding/json" "fmt" "os" ) type Website struct { // 由于权限问题,结构体转json数据格式时会主动频闭掉小写字母开头的数据 // 结构体转json需要将共享的字段进行大写 Name string `xml:"Name,attr"` Url string Course []string } func main() { //数据 info := []Website{{"Golang", "http://c.biancheng.net/golang/", []string{"http://c.biancheng.net/cplus/", "http://c.biancheng.net/linux_tutorial/"}}, {"Java", "http://c.biancheng.net/java/", []string{"http://c.biancheng.net/socket/", "http://c.biancheng.net/python/"}}} // 创建json文件 // fmt.Println(info) fp, err := os.Create("info.json") if err != nil { fmt.Println("文件创建失败!", err.Error()) return } //延时执行fp.Close() defer fp.Close() // 使用打开的文件创建json编码器 encoder := json.NewEncoder(fp) //将json数据编码进文件内 err = encoder.Encode(info) if err != nil { fmt.Println("编码错误", err.Error()) } else { fmt.Println("编码成功!") } fmt.Println("hello") }
①读文件
代码如下(示例):
package main import ( "encoding/json" "fmt" "os" ) type Website struct { Name string Url string Course []string } func main() { fp, err := os.Open("info.json") if err != nil { fmt.Println("文件打开失败!", err.Error()) return } defer fp.Close() var info []Website // 创建json编码器(将json文件与json对象进行绑定) decoder := json.NewDecoder(fp) // 从json对象绑定的json文件读取数据 err = decoder.Decode(&info) if err != nil { fmt.Println("解码失败!") return } else { fmt.Println(info) } // json数据格式对象返回的是键值对 for temp, v := range info { fmt.Println(temp, v) } fmt.Println("123") }
2.操作xml文件
①写文件
代码如下(示例):
package main import ( "encoding/xml" "fmt" "os" ) /* 使用go语言进行xml格式文件处理的时候,需要一一对应标签 */ type Website struct { Name string `xml:"Name,attr"` Url string //`xml:"Url>Course"` Course []string } func main() { //实例化对象 info := []Website{{"C语言中文网", "http://c.biancheng.net/golang/", []string{"Go语言入门教程", "Golang入门教程"}}, {"python程序设计", "http://c.biancheng.net/golangs/", []string{"人工智能", "网络爬虫"}}} fp, err := os.Create("info.xml") if err != nil { fmt.Println("出错了!", err.Error()) return } defer fp.Close() // 序列化到文件 encoder := xml.NewEncoder(fp) err = encoder.Encode(info) if err != nil { fmt.Println("编码错误!", err) } else { fmt.Println("编码成功!") } fmt.Println("123") }
②读文件
代码如下(示例):
package main import ( "encoding/xml" "fmt" "os" ) type Website struct { Name string `xml:"Name,attr"` Url string `xml:"Url>Course"` Course []string } func main() { // 打开一个文件 fp, err := os.Open("info.xml") if err != nil { fmt.Println("打开失败!") return } defer fp.Close() info := []Website{} // 加载一个解码器 decoder := xml.NewDecoder(fp) // 值得注意的是,读取xml文件时不是将数据一次读取完,而是每次读取一行组数据 err = decoder.Decode(&info) err = decoder.Decode(&info) if err != nil { fmt.Println("解码失败!", err) } else { fmt.Println(info) } fmt.Println("123") }
3.操作gob文件
①读、写文件
代码如下:
package main import ( "encoding/gob" "fmt" "os" ) /* gob是 Go Binary的简写,是将go语言结构体进行序列化的一种方式,gob文件属于自描述文件,他里面包含所有类型的自描述 进行解码的时候不需要了解文件的内容,在编码解码过程中,零值会被忽略,在解码过程中只有只有匹配名称,和可兼容字段才会被 解码 */ func main() { // 创建对象 info := map[string]string{ "name": "C语言中文网", "website": "http://c.biancheng.net/golang/", } name := "demo.gob" fp, err := os.Create(name) if err != nil { fmt.Println("创建失败!", err) return } defer fp.Close() // 创建编码器,进行编码序列化进文件 encoder := gob.NewEncoder(fp) err = encoder.Encode(info) if err != nil { fmt.Println("编码失败!", err) } else { fmt.Println("编码成功!") } // 移动文件描述符,将文件内的光标移到开头 // 第一个参数是偏移量,第二个参数0代表开头,1代表自身,2代表文件末尾 fp.Seek(0, 0) // 加载一个解码器,对前面创建的文件进行解码 decoder := gob.NewDecoder(fp) var infos map[string]string err = decoder.Decode(&infos) if err != nil { fmt.Println("error", err) fmt.Println("解码失败!") return } else { fmt.Println("解码成功!") } // 打印解码出来的数据 for k := range infos { fmt.Println(k, "对应的值是:", infos[k]) } fmt.Println("123") }
4.操作普通文本文件
①读、写文件
代码如下:
package main import ( "bufio" "fmt" "io" "os" ) func main() { // 打开一个文件 fp, err := os.Create("text.txt") if err != nil { fmt.Println("创建失败!", err) } defer fp.Close() // 写入内容 writer := bufio.NewWriter(fp) // 写入时先将东西写入缓冲区 writer.WriteString("hello\nTom\n") // 想要将缓冲区的数据写入磁盘就需要刷新缓冲区 writer.Flush() // 文件光标移到初始位置 fp.Seek(0, 0) read := bufio.NewReader(fp) for { str, err := read.ReadString('\n') //表示一次读一行,其中传进去的是每次中断的符号 if err == io.EOF { break } fmt.Print(str) } fmt.Println("hello") }
5.操作普通二进制文本文件
①读、写文件
普通二进制文件与gob二进制文件的区别就是普通二进制文件不带自描述,必须人为按照一定的数据格式进行解码
代码如下:
package main import ( "bytes" "encoding/binary" "fmt" "os" ) type WebSite struct { Url int32 } func main() { fp, err := os.Create("text.bin") if err != nil { fmt.Println("创建失败!", err) } defer fp.Close() for i := 0; i < 10; i++ { info := WebSite{int32(i)} var bin_buf bytes.Buffer binary.Write(&bin_buf, binary.LittleEndian, info) b := bin_buf.Bytes() _, err = fp.Write(b) if err != nil { fmt.Println("编码失败!", err) return } } fmt.Println("123") }
6.操作压缩文件
①读、写文件
对压缩文件进行层次化的压缩与解压缩
代码如下:
package main import ( "archive/zip" "bytes" "fmt" "io" "os" ) func main() { // 创建一个缓冲区用来保存文件内容 buf := new(bytes.Buffer) // 创建一个压缩文件夹 w := zip.NewWriter(buf) // 将文件加入压缩文档 var file = []struct { Name, Body string }{ {"GoLong", "https666"}} // 迭代数据,使用数据创建文件 for _, file := range file { // 在压缩文档内创建文件 f, err := w.Create(file.Name) if err != nil { fmt.Println(err) } // 在创建好的文件内写数据 _, err = f.Write([]byte(file.Body)) if err != nil { fmt.Println(err) } } // 关闭压缩文档 err := w.Close() if err != nil { fmt.Println(err) } f, err := os.Create("file.zip") if err != nil { fmt.Println(err) } // 将缓冲区的东西写到f文件内 buf.WriteTo(f) // 读取压缩文件中的内容 // 打开一个zip格式文件 r, err := zip.OpenReader("file.zip") if err != nil { fmt.Println(err) } defer r.Close() // 迭代压缩文件 for _, f := range r.File { fmt.Printf("文件名:%s\n", f.Name) rc, err := f.Open() if err != nil { fmt.Println(err) } _, err = io.CopyN(os.Stdout, rc, int64(f.UncompressedSize64)) if err != nil { fmt.Println(err.Error()) } rc.Close() } fmt.Println("123") }
总结
这里仅仅介绍了各种文件的简单读写操作方式,如果熟练地操作各种文件还需要参考官方文档。