<span style="font-size: 15px;">archive</span>
および <span style="font-size: 15px;">compress</span>
がこれらの機能を提供します。 , この記事の例を通して、Go プログラミングを使用して圧縮パッケージ ファイルを生成および処理するのが非常に簡単であることがわかります。 コードを開始する前に、パッケージ化と圧縮の概念を明確にする必要があります。
# パッケージング ツール tar を例に挙げると、このツールによって生成されるファイルは通常 tar パッケージと呼ばれ、ファイル名は通常 .tar で終わります。次に、gzip 圧縮などの他の圧縮ツールを使用して tar パッケージを圧縮すると、通常 .tar.gz という名前の圧縮ファイルが得られます (gzip は tar の -z パラメータで呼び出すことができます)。
tar パッケージはファイルの集合であり、その構造もデータ セグメントで構成されており、各データ セグメントにはファイル ヘッダー (ファイルを説明するメタ情報) とファイルの内容が含まれています。
+----------------------------------------+ | Header | | [name][mode][owner][group][size] ... | +----------------------------------------+ | Content | | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| +----------------------------------------+ | Header | | [name][mode][owner][group][size] ... | +----------------------------------------+ | Content | | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| +----------------------------------------+ | ... |
アーカイブ アーカイブ ライブラリの中国語の意味は、アーカイブとその機能です。アーカイブ (パッケージング) とアンパック (解凍) です。 tar と zip の 2 つのソリューションが提供されます。呼び出しパスは、それぞれ archive/tar<span style="font-size: 15px;"></span>
と archive/zip## です。 . <span style="font-size: 15px;"></span>#。
まず、新しいターゲット パッケージング ファイルを out.tar として作成し、次にアーカイブ用のファイル データ readme.txt、gopher.txt、および todo.txt を構築します。
接着依次构建文件头信息,分别指定了文件名、权限和大小(可定义更多文件头字段),再通过 执行以上代码,将得到打包后的 out.tar 文件,可通过 tar 工具指定 -tvf 参数查看归档信息。 可以看到,指定的文件信息(文件名、权限和大小)符合预期,但其他未指定的元信息是有误的,例如日期(直接给的默认值)。 如果通过 tar 工具,我们可以执行以下命令来提取 out.tar 中的文件。 但在程序中实现,应该怎么做呢? 首先需要打开 out.tar,并构造 compress 库中支持了多种压缩方案,包括 bzip2、flate、gzip、lzw 和 zlib,调用路径为 我们以常用的 gzip 为例,来展示压缩与解压缩代码。 如果同样是上文中的文件数据 readme.txt、gopher.txt 和 todo.txt,我们想得到 tar 归档且被压缩了的 out.tar.gz 文件,应该如何做呢? 非常简单!只需要将 我们比较有压缩与无压缩的归档 tar 包大小,可以看到文件体积从4.0K压缩为了224B。 同理,如果要解压并解包 out.tar.gz 文件,应该如何做呢?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)
}
}
}
$ 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 -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.
<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 库压缩与解压缩
<span style="font-size: 15px;">compress/xxx</span>
。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>
而来。$ 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
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 设计。
もちろん、私はこの問題を詳細に実行する必要があることだけを知っています。 <span style="font-size: 15px;">archive</span>
ライブラリと <span style="font-size: 15px;">compress</span>
ライブラリを使用したことがない読者は、この記事を試すことができます。パッケージ化された圧縮ファイルを処理しようとする未使用のソリューション。
以上がGo でファイルをパックして圧縮する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。