Golang:将文件附加到现有的tar存档

Jef*_*eff 6 go

如何将文件附加到Go中的现有tar存档?我没有在文档中看到有关如何做到这一点的任何明显内容.

我有一个已经创建的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()

}
Run Code Online (Sandbox Code Playgroud)

Int*_*net 11

tar文件规范状态:

tar存档由一系列512字节的记录组成.每个文件系统对象都需要一个头记录,它存储基本元数据(路径名,所有者,权限等)和包含任何文件数据的零个或多个记录.存档的结尾由两个完全由零字节组成的记录表示.

添加这两个零填充记录的Go实现在这里发生.

要绕过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)
Run Code Online (Sandbox Code Playgroud)

附:

f, err = os.OpenFile("/home/jeff/Desktop/test.tar", os.O_RDWR, os.ModePerm)
if err != nil {
    log.Fatalln(err)
}
if _, err = f.Seek(-1024, os.SEEK_END); err != nil {
    log.Fatalln(err)
}
tw = tar.NewWriter(f)
Run Code Online (Sandbox Code Playgroud)

它打开文件读/写(而不是追加/只写),然后在文件结束之前寻找1024字节并从那里写入.

它有效,但它一个可怕的黑客.

编辑:在了解tar文件规格稍微好一点后,我不再相信这是一个黑客.

完整代码:http://play.golang.org/p/0zRScmY4AC

  • 我不认为这是一个可怕的 hack * all *,它完全在规范的范围内,并且只会在最后 1024 个字节不是预告块的文件上失败。当然,这只会发生在,例如,您创建了自己的 tar 包(复制了源代码)并在 tw.Close() 调用中注释掉了预告片部分。 (3认同)