go文件操作实践[读写zip tar xlsx文件]
这篇我接着实践zip,tar和xlsx文件的读写操作。简单介绍一下 tar吧:
tar 是一种打包格式,但不对文件进行压缩,所以打包后的文档一般远远大于 zip 和 tar.gz,因为不需要压缩的原因,所以打包的速度是非常快的,打包时 CPU 占用率也很低。
tar 的目的在于方便文件的管理,比如在我们的生活中,有很多小物品分散在房间的各个角落,为了方便整洁可以将这些零散的物品整理进一个箱子中,而 tar 的功能就类似这样。
创建 tar 归档文件与创建 .zip 归档文件非常类似,主要不同点在于我们将所有数据都写入相同的 writer 中,并且在写入文件的数据之前必须写入完整的头部,而非仅仅是一个文件名。
tar 打包实现原理如下:
创建一个文件 x.tar,然后向 x.tar 写入 tar 头部信息;
打开要被 tar 的文件,向 x.tar 写入头部信息,然后向 x.tar 写入文件信息;
当有多个文件需要被 tar 时,重复第二步直到所有文件都被写入到 x.tar 中;
关闭 x.tar,完成打包
package main import ( "archive/tar" "archive/zip" "bytes" "fmt" "io" "os" "strings" "github.com/tealeg/xlsx" ) type Website struct { Name string `xml:"name,attr"` Content []string } var info []Website func init() { info = []Website{ {"Golang.txt", []string{"http://c.biancheng.net/cplus/", "http://c.biancheng.net/linux_tutorial/"}}, {"Java.txt", []string{"http://c.biancheng.net/socket/", "http://c.biancheng.net/python/"}}, } /* 列举了一些常用的 flag 文件处理参数: O_RDONLY:只读模式打开文件; O_WRONLY:只写模式打开文件; O_RDWR:读写模式打开文件; O_APPEND:写操作时将数据附加到文件尾部(追加); O_CREATE:如果不存在将创建一个新文件; O_EXCL:和 O_CREATE 配合使用,文件必须不存在,否则返回一个错误; O_SYNC:当进行一系列写操作时,每次都要等待上次的 I/O 操作完成再进行; O_TRUNC:如果可能,在打开时清空文件。 */ } // 检查文件或目录是否存在 // 如果由 filename 指定的文件或目录存在则返回 true,否则返回 false func IsExist(filename string) bool { _, err := os.Stat(filename) return err == nil || os.IsExist(err) } func main() { WriteZip() ReadZip() WriteTar() ReadTar() WriteXlsx() ReadXlsx() } func WriteZip() { // 创建一个缓冲区用来保存压缩文件内容 buf := new(bytes.Buffer) // 创建一个压缩文档 w := zip.NewWriter(buf) // 创建文件 写入内容 for _, file := range info { f, err := w.Create(file.Name) if err != nil { fmt.Printf("create zip fiel [%s] has error:%v \r\n", file.Name, err) return } for _, content := range file.Content { _, err = f.Write([]byte(content + "\r\n")) if err != nil { fmt.Printf("zip write content [%s] has error:%v\r\n", content, err) } } } // 关闭压缩文档 err := w.Close() if err != nil { fmt.Printf("zip close has error:%v\r\n", err) } // 将压缩文档内容写入文件 path := "./file.zip" if IsExist(path) { os.Remove(path) } f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0666) defer f.Close() if err != nil { fmt.Printf("zip create has error:%v\r\n", err) } buf.WriteTo(f) fmt.Println("zip create done") } func ReadZip() { path := "./file.zip" if !IsExist(path) { fmt.Printf("zip file [%s] not exist\r\n", path) return } // 打开一个zip格式文件 r, err := zip.OpenReader(path) if err != nil { fmt.Printf("zip read[OpenReader] has error:%v\r\n", err) return } defer r.Close() // 迭代压缩文件中的文件,打印出文件中的内容 for _, f := range r.File { fmt.Printf("ReadZip open file: %s\n", f.Name) rc, err := f.Open() if err != nil { fmt.Printf(err.Error()) } _, err = io.CopyN(os.Stdout, rc, int64(f.UncompressedSize64)) if err != nil { fmt.Printf(err.Error()) } rc.Close() } } /* tar 打包实现原理如下: 创建一个文件 x.tar,然后向 x.tar 写入 tar 头部信息; 打开要被 tar 的文件,向 x.tar 写入头部信息,然后向 x.tar 写入文件信息; 当有多个文件需要被 tar 时,重复第二步直到所有文件都被写入到 x.tar 中; 关闭 x.tar,完成打包。 */ func WriteTar() { path := "./output.tar" if IsExist(path) { os.Remove(path) } f, err := os.Create(path) //创建一个 tar 文件 if err != nil { fmt.Printf("create tar has error %v\r\n", err) return } defer f.Close() tw := tar.NewWriter(f) defer tw.Close() for _, file := range info { //preare file f, err := os.Create(file.Name) if err != nil { fmt.Printf("create tar fiel [%s] has error:%v \r\n", file.Name, err) return } for _, content := range file.Content { _, err = f.Write([]byte(content + "\r\n")) if err != nil { fmt.Printf("tar write content [%s] has error:%v\r\n", content, err) } } f.Close() /// fileInfo, _ := os.Stat("./" + file.Name) hdr, err := tar.FileInfoHeader(fileInfo, "") if err != nil { fmt.Println(err) } err = tw.WriteHeader(hdr) //写入头文件信息 if err != nil { fmt.Println(err) } f1, err := os.Open("./" + file.Name) if err != nil { fmt.Println(err) return } m, err := io.Copy(tw, f1) //将main.exe文件中的信息写入压缩包中 if err != nil { fmt.Println(err) } fmt.Println(m) } fmt.Println("tar wirte done") } func ReadTar() { path := "./output.tar" if !IsExist(path) { fmt.Printf("tar file [%s] not exist\r\n", path) return } f, err := os.Open(path) if err != nil { fmt.Println("文件打开失败", err) return } defer f.Close() r := tar.NewReader(f) for hdr, err := r.Next(); err != io.EOF; hdr, err = r.Next() { if err != nil { fmt.Println(err) return } fileinfo := hdr.FileInfo() fmt.Println(fileinfo.Name()) /* f, err := os.Create("123" + fileinfo.Name()) if err != nil { fmt.Println(err) } defer f.Close() */ _, err = io.Copy(os.Stdout, r) if err != nil { fmt.Println(err) } } } func WriteXlsx() { path := "./info.xlsx" if IsExist(path) { os.Remove(path) } xlsxfile := xlsx.NewFile() ///创建sheet 写入数据 for _, file := range info { fileName := strings.Replace(file.Name, ".txt", "", 1) sheet, err := xlsxfile.AddSheet(fileName) if err != nil { fmt.Printf("xlsx create sheet [%s] has error %v\r\n", fileName, err) continue } row := sheet.AddRow() row.SetHeightCM(1) cell := row.AddCell() cell.Value = "Content" for _, content := range file.Content { addRow := sheet.AddRow() addCell := addRow.AddCell() addCell.Value = content } } err := xlsxfile.Save(path) if err != nil { fmt.Printf("xlsx save has error:%v\r\n", err) } fmt.Println("write xlsx done") } func ReadXlsx() { path := "./info.xlsx" if !IsExist(path) { return } // 读取文件内容 xlFile, err := xlsx.OpenFile(path) if err != nil { fmt.Printf("read xlsx has error %v\r\n", err) } for name, sheet := range xlFile.Sheet { fmt.Println(name) for rowindex, row := range sheet.Rows { for cellindex, cell := range row.Cells { fmt.Printf("sheet [%s] %d rows %d cell=%s\r\n", name, rowindex, cellindex, cell.Value) } } } fmt.Println("read xlsx done") }
windows技术爱好者