Golang:将文件附加到现有的tar档案 [英] Golang: append file to an existing tar archive

查看:130
本文介绍了Golang:将文件附加到现有的tar档案的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我如何将文件追加到Go中的现有tar档案中?在文档中,我没有看到有关如何执行此操作的任何明显信息。



我已经创建了一个tar文件,我想在它已经关闭之后再添加一个。



编辑



更改文档中的示例并根据给出的答案,我仍然没有得到预期的结果。前三个文件正在写入tar,但是当我关闭并再次打开文件以写入文件时,新文件永远不会被写入。代码运行良好。我不知道我在想什么。



以下代码给我一个包含三个文件的tar文件:readme.txt,gopher.txt,todo。文本。

 包主
$ b $导入(
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 {
名称,正文字符串
} {
{readme.txt,该存档包含一些文本文件。 },
{gopher.txt,Gopher名称:\George\Geoffrey\\\
Gonzo},
{todo.txt,获取动物处理许可证},
}
为_,file:=范围文件{
hdr:=& tar.Header {
名称:file.Name,
大小: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()

//打开文件并添加更多内容

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:=这是一个测试

hdr:=& tar.Header {
名称:foo.bar,
大小: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()

}


解决方案




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



执行添加这两个零填充记录的执行发生在这里为了避开 tar 文件格式的预告片(基本上没有任何东西是1024个字节),你可以使用
$ b 替换这些行:

  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 文件规范后,我不再相信这是一种破解。

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


How would I append a file to an existing tar archive in Go? I don't see anything obvious in the docs on how to do it.

I have a tar file that has already been created and I want to add more to it after it has already been closed.

EDIT

Altering the example in the docs and following the answer given, I'm still not getting the expected result. The first three files are being written to the tar but when I close and open up the file again to write to it, the new file is never being written. The code runs fine. I don't know what I'm missing.

The following code gives me a tar file with three files in it: readme.txt, gopher.txt, todo.txt. foo.bar never gets written.

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()

}

解决方案

The tar file specification states:

A tar archive consists of a series of 512-byte records. Each file system object requires a header record which stores basic metadata (pathname, owner, permissions, etc.) and zero or more records containing any file data. The end of the archive is indicated by two records consisting entirely of zero bytes.

The Go implementation of adding these two zero filled records happens here .

To get around the tar file format trailer (basically 1024 bytes of nothing) you could replace the lines:

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)

With:

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)

It opens the file read / write (instead of append / write-only) and then seeks to 1024 bytes before the end of the file and writes from there.

It works, but it is a horrible hack.

EDIT: After understanding the tar file spec a little better, I no longer believe this is such a hack.

Full code: http://play.golang.org/p/0zRScmY4AC

这篇关于Golang:将文件附加到现有的tar档案的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆