Heim > Artikel > Backend-Entwicklung > So packen und komprimieren Sie Dateien in Go
<span style="font-size: 15px;">archive</span>
与<span style="font-size: 15px;">compress</span>
archive und
Verpackung und Komprimierung
🎜🎜🎜Bevor wir mit dem Code beginnen, müssen wir die Konzepte der Verpackung und Komprimierung klären. 🎜🎜Nehmen Sie als Beispiel das Verpackungstool tar. Die von ihm erstellten Dateien werden normalerweise als TAR-Pakete bezeichnet und ihre Dateinamen enden normalerweise mit .tar. Komprimieren Sie dann das TAR-Paket mit anderen Komprimierungstools, z. B. der GZIP-Komprimierung, und Sie erhalten eine komprimierte Datei, die normalerweise mit .tar.gz benannt wird (in TAR können Sie den Parameter -z verwenden, um GZIP aufzurufen).
tar-Paket ist eine Sammlung von Dateien, und seine Struktur besteht ebenfalls aus Datensegmenten. Jedes Datensegment enthält den Dateikopf (Metainformationen, die die Datei beschreiben) und den Dateiinhalt.
+----------------------------------------+ | Header | | [name][mode][owner][group][size] ... | +----------------------------------------+ | Content | | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| +----------------------------------------+ | Header | | [name][mode][owner][group][size] ... | +----------------------------------------+ | Content | | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| +----------------------------------------+ | ... |
Archiv Die chinesische Bedeutung der Archivbibliothek ist Archive, und ihre Funktion besteht darin, zu archivieren (verpacken) und zu entpacken (auspacken). Es bietet zwei Lösungen: tar und zip, und die Aufrufpfade sind <code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #000000;background: rgba(14, 210, 247, 0.15);"><span style="font-size: 15px;">archive/tar</span>
和<span style="font-size: 15px;">archive/zip</span>
archive/tar und
<p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 0;line-height: 26px;color: black;font-size: 17px;word-spacing: 3px;letter-spacing: 1px;">archive/zip<span style="font-size: 15px;"></span></p>
. Wir nehmen tar als Beispiel, um zu zeigen, wie Dateien verpackt und entpackt werden.
🎜🎜🎜Erstellen Sie zunächst eine neue Zielverpackungsdatei als out.tar und erstellen Sie dann einige Dateidaten readme.txt, gopher.txt und todo.txt zur Archivierung. 🎜🎜import ( "archive/tar" ... ) func main() { // Create and add some files to the archive. tarPath := "out.tar" tarFile, err := os.Create(tarPath) if err != nil { log.Fatal(err) } defer tarFile.Close() tw := tar.NewWriter(tarFile) defer tw.Close() var files = []struct { Name, Body string }{ {"readme.txt", "This archive contains some text files."}, {"gopher.txt", "Gopher names:\nGeorge\nGeoffrey\nGonzo"}, {"todo.txt", "Get animal handling license."}, } ... }
接着依次构建文件头信息,分别指定了文件名、权限和大小(可定义更多文件头字段),再通过<span style="font-size: 15px;">*tar.Writer</span>
类型的 tw 变量,按序调用<span style="font-size: 15px;">WriteHeader</span>
和<span style="font-size: 15px;">Write</span>
方法将需要打包的数据段(文件头+文件内容)写入到out.tar文件。
... for _, file := range files { hdr := &tar.Header{ Name: file.Name, Mode: 0600, Size: int64(len(file.Body)), } if err := tw.WriteHeader(hdr); err != nil { log.Fatal(err) } if _, err := tw.Write([]byte(file.Body)); err != nil { log.Fatal(err) } } }
执行以上代码,将得到打包后的 out.tar 文件,可通过 tar 工具指定 -tvf 参数查看归档信息。
$ tar -tvf out.tar -rw------- 0 0 0 38 Jan 1 1970 readme.txt -rw------- 0 0 0 35 Jan 1 1970 gopher.txt -rw------- 0 0 0 28 Jan 1 1970 todo.txt
可以看到,指定的文件信息(文件名、权限和大小)符合预期,但其他未指定的元信息是有误的,例如日期(直接给的默认值)。
如果通过 tar 工具,我们可以执行以下命令来提取 out.tar 中的文件。
$ tar -xvf out.tar x readme.txt x gopher.txt x todo.txt
但在程序中实现,应该怎么做呢?
func main() { tarPath := "out.tar" tarFile, err := os.Open(tarPath) if err != nil { log.Fatal(err) } defer tarFile.Close() tr := tar.NewReader(tarFile) for { hdr, err := tr.Next() // End of archive if err == io.EOF { break } if err != nil { log.Fatal(err) } fmt.Printf("Contents of %s: ", hdr.Name) if _, err := io.Copy(os.Stdout, tr); err != nil { log.Fatal(err) } fmt.Println() } } // Output: Contents of readme.txt: This archive contains some text files. Contents of gopher.txt: Gopher names: George Geoffrey Gonzo Contents of todo.txt: Get animal handling license.
首先需要打开 out.tar,并构造<span style="font-size: 15px;">*tar.Reader</span>
类型的 tr 变量。之后,利用<span style="font-size: 15px;">tr.Next</span>
依次提取每个数据段内容,并通过 io.Copy(os.Stdout, tr),将文件内容拷贝至标准输出。直到<span style="font-size: 15px;">tr.Next</span>
遇到<span style="font-size: 15px;">io.EOF</span>
,它代表读取到了归档文件末尾,则退出提取。
compress 库中支持了多种压缩方案,包括 bzip2、flate、gzip、lzw 和 zlib,调用路径为<span style="font-size: 15px;">compress/xxx</span>
。
我们以常用的 gzip 为例,来展示压缩与解压缩代码。
如果同样是上文中的文件数据 readme.txt、gopher.txt 和 todo.txt,我们想得到 tar 归档且被压缩了的 out.tar.gz 文件,应该如何做呢?
package main import ( "archive/tar" "compress/gzip" ... ) func main() { tarPath := "out.tar.gz" tarFile, err := os.Create(tarPath) if err != nil { log.Fatal(err) } defer tarFile.Close() gz := gzip.NewWriter(tarFile) defer gz.Close() tw := tar.NewWriter(gz) defer tw.Close() ... }
非常简单!只需要将<span style="font-size: 15px;">tar.NewWriter(tarFile)</span>
改为<span style="font-size: 15px;">tar.NewWriter(gz)</span>
即可,其中<span style="font-size: 15px;">gz</span>
是由<span style="font-size: 15px;">gzip.NewWriter(tarFile)</span>
而来。
我们比较有压缩与无压缩的归档 tar 包大小,可以看到文件体积从4.0K压缩为了224B。
$ ls -alh out.tar out.tar.gz -rw-r--r-- 1 slp staff 4.0K Jul 3 21:52 out.tar -rw-r--r-- 1 slp staff 224B Jul 3 21:53 out.tar.gz
同理,如果要解压并解包 out.tar.gz 文件,应该如何做呢?
package main import ( "archive/tar" "compress/gzip" ... ) func main() { tarPath := "out.tar.gz" tarFile, err := os.Open(tarPath) if err != nil { log.Fatal(err) } defer tarFile.Close() gz, err := gzip.NewReader(tarFile) if err != nil { log.Fatal(err) } defer gz.Close() tr := tar.NewReader(gz) ... }
依然很简单!只需要将<span style="font-size: 15px;">tar.NewReader(tarFile)</span>
改为<span style="font-size: 15px;">tar.NewReader(gz)</span>
即可,其中<span style="font-size: 15px;">gz</span>
是由<span style="font-size: 15px;">gzip.NewReader(tarFile)</span>
而来。
本文展示了如何通过archive/tar
包实现文件的打包与解包操作,如何通过<span style="font-size: 15px;">compress/gzip</span>
包对tar包开展进一步的压缩与解压缩。
在展示<span style="font-size: 15px;">compress/gzip</span>
使用时,多封装一层Writer/Reader,即可为tar归档文件增加压缩与解压缩功能。更棒的是,如果你想切换打包/解包、压缩/解压缩策略,仅仅替换掉对应的 Writer/Reader 即可。而这种便利,源于 Go 优秀的流式 IO 设计。
Natürlich weiß ich nur, dass diese Angelegenheit im Detail erledigt werden muss. Nie verwendet
und <span style="font-size: 15px;">archive</span>
和<span style="font-size: 15px;">compress</span>
archive
Das obige ist der detaillierte Inhalt vonSo packen und komprimieren Sie Dateien in Go. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!