如何将文件附加到Go中的现有tar存档?我在docs中没有看到任何关于如何做到这一点的明显内容。
我有一个已经创建的tar文件,我想在它关闭后添加更多文件。
修改
改变文档中的示例并按照给出的答案,我仍然没有得到预期的结果。前三个文件正在写入tar,但当我关闭并再次打开文件写入时,新文件永远不会被写入。代码运行正常。我不知道我错过了什么。
以下代码为我提供了一个包含三个文件的tar文件:readme.txt,gopher.txt,todo.txt。 foo.bar从未写过。
package main
import (
"archive/tar"
"log"
"os"
)
func main() {
f, err := os.Create("/home/jeff/Desktop/test.tar")
if err != nil {
log.Fatalln(err)
}
tw := tar.NewWriter(f)
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 licence."},
}
for _, file := range files {
hdr := &tar.Header{
Name: file.Name,
Size: int64(len(file.Body)),
}
if err := tw.WriteHeader(hdr); err != nil {
log.Fatalln(err)
}
if _, err := tw.Write([]byte(file.Body)); err != nil {
log.Fatalln(err)
}
}
if err := tw.Close(); err != nil {
log.Fatalln(err)
}
f.Close()
// Open up the file and append more things to it
f, err = os.OpenFile("/home/jeff/Desktop/test.tar", os.O_APPEND|os.O_WRONLY, os.ModePerm)
if err != nil {
log.Fatalln(err)
}
tw = tar.NewWriter(f)
test := "this is a test"
hdr := &tar.Header{
Name: "foo.bar",
Size: int64(len(test)),
}
if err := tw.WriteHeader(hdr); err != nil {
log.Fatalln(err)
}
if _, err := tw.Write([]byte(test)); err != nil {
log.Fatalln(err)
}
if err := tw.Close(); err != nil {
log.Fatalln(err)
}
f.Close()
}
答案 0 :(得分:11)
tar存档由一系列512字节的记录组成。每个文件系统 对象需要一个存储基本元数据的头记录(路径名, 所有者,权限等)以及包含任何文件的零个或多个记录 数据。存档的结尾由两个记录组成 完全是零字节。
Go实现添加这两个零填充记录happens here。
要绕过tar
文件格式预告片(基本上只有1024字节),您可以替换这些行:
f, err = os.OpenFile("/home/jeff/Desktop/test.tar", os.O_APPEND|os.O_WRONLY, os.ModePerm)
if err != nil {
log.Fatalln(err)
}
tw = tar.NewWriter(f)
使用:
f, err = os.OpenFile("/home/jeff/Desktop/test.tar", os.O_RDWR, os.ModePerm)
if err != nil {
log.Fatalln(err)
}
if _, err = f.Seek(-2<<9, os.SEEK_END); err != nil {
log.Fatalln(err)
}
tw = tar.NewWriter(f)
它打开文件读/写(而不是追加/只写),然后在文件结束之前寻找1024字节并从那里写入。
它有效,但 是一个可怕的黑客。
编辑:在更好地理解tar
文件规范之后,我不再相信这是一个黑客攻击。
答案 1 :(得分:2)
它只是一个编写器接口,所以在写完文件头后写入字节。
import (
"archive/tar"
"os"
)
f, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY, os.ModePerm)
if err != nil {
// handle error here
}
hdr := tar.Header{}
// populate your header
tw := tar.NewWriter(f)
// append a file
tw.WriteHeader(hdr)
tw.Write(content_of_file_as_bytes)
http://golang.org/pkg/archive/tar/#Writer告诉你所有你需要知道的事情。
编辑:事实证明,tar文件在关闭时会将一个预告片写到最后。因此,即使您将新数据写入tar存档,也不会通过该预告片读取。因此,看起来您必须首先读取tar存档,然后将整个存档重写为磁盘,这是次优的。该软件包不支持附加到它们的必要内容,因此这是我现在可以推荐的最佳内容。