在 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()
}
最佳答案
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.
添加这两条零填充记录的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(-1024, os.SEEK_END); err != nil {
log.Fatalln(err)
}
tw = tar.NewWriter(f)
它以读/写方式打开文件(而不是追加/只写),然后查找文件末尾之前的 1024 字节并从那里开始写入。
它有效,但它是一个可怕的 hack。
编辑:在更好地理解了 tar 文件规范之后,我不再相信这是一个 hack。
关于戈朗 : append file to an existing tar archive,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18323995/
关闭。这个问题需要更多focused.它目前不接受答案。想改进这个问题吗?更新问题,使其只关注一个问题editingthispost.关闭3年前。Improvethisquestion告诉我如何使用Golang登录网站。下载xls文件是得到了,但是为了在Excel表格中有数据,需要登录网站。该站点位于公司的服务器上。如果你能告诉你怎么做。例如,我用来执行此操作的VBA代码。SetoFields=CreateObject("Scripting.Dictionary")WithoFields.Add"login","sdiscor".Add"password","sdiscor"EndWi
下面是我查询的代码:我有一个单维数组a当我打印a[0][0]时,我不明白为什么它返回字符a的ascii值:packagemainimport("fmt")funcmain(){a:=[3]string{"a","b","c"}fmt.Println(a[0][0])}输出:97 最佳答案 下面是如何打印ascii的代码示例a:=[3]string{"a","b","c"}for_,rune:=rangea{fmt.Println(rune)//Itwillprinta,b,c}因为你在你的代码中使用了[0][0],所以它是等价的fo
typepath[]bytefunc(ppath)ToUpper(){fori,b:=rangep{if'a'在上面(这个例子是从“TheGoBlog”复制过来的),如果ToUpper变成这样:func(ppath)ToUpper(){fori,_:=rangep{if'a'哪个会更有效率为什么?“TheGoBlog”对前一个说:“这里的ToUpper方法在forrange构造中使用两个变量来捕获索引和slice元素。这种形式的循环避免了在主体中多次写入p[i]。”什么意思? 最佳答案 前者有更多的内存操作,即在b上:它在循环的第一
我有一个用Golang编写的脚本,我不太明白。我想知道他为什么要在脚本里面写goserver.Start()?为什么不简单地编写server.Start?packagemainimport("github.com/miekg/dns""testing""time")constTEST_ADDR="127.0.0.1:9953"funcTestDNSResponse(t*testing.T){server:=NewDNSServer(&Config{dnsAddr:TEST_ADDR,})goserver.Start()//Allowsometimeforservertostarttim
我正在尝试在Go中做一些相对简单的事情——将字符串转换为整数,然后将其加倍:myInt,_:=strconv.Atoi(args[1])doubleArg:=myInt*2由于Atoi()返回两个参数(整数和err),我使用myInt,_:=来检索值的整数。我想将它加倍(因此是第二行)但不能在一行中完成所有操作:myInt,_:=strconv.Atoi(args[1])*2给我:multiple-valuestrconv.Atoi()insingle-valuecontext但是,根据我使用大多数其他语言的经验,必须在两行中执行此操作似乎有很多样板。这只是我必须处理的一个限制,还是有
我刚接触golang。尝试通过golang实现批量上传到Elasticsearch。我正在使用golang库->https://github.com/olivere/elastic用于与Elasticsearch通信。此外,我正在尝试一段示例代码,但出现以下错误...suresh@BLR-245:~/Desktop/tools/golang/src$goinstallgithub.com/crazyheart/elastic-bulk-upload#github.com/crazyheart/elastic-bulk-uploadgithub.com/crazyheart/elasti
我计划实现一个go-routine并有一个sync.WaitGroup同步创建的go-routine的结尾。我基本上使用go创建了一个线程.所以它是这样的:main(){varwgsync.WaitGroupfor{gomyThread(wg)wg.Add(1)}wg.wait()}myThread(wgsync.WaitGroup){deferwg.Done()}我之前曾与pthread_create合作过在某些情况下确实无法创建线程。在这种情况下,是否可能针对上述gomyThread(wg)无法启动和/或运行wg.Done()例程的其余部分是否正常运行?如果是这样,将报告什么以及如
Go的append()函数仅在给定slice的容量不足时分配新的slice数据(另请参见:https://stackoverflow.com/a/28143457/802833)。这可能会导致意外行为(至少对我这个golang新手来说):packagemainimport("fmt")funcmain(){a1:=make([][]int,3)a2:=make([][]int,3)b:=[][]int{{1,1,1},{2,2,2},{3,3,3}}common1:=make([]int,0)common2:=make([]int,0,12)//providesufficientcap
我需要编写一个测试来验证服务器响应。响应必须包含某些header和xml正文。首先,如何检查响应中是否存在所需的header。以及如何比较收到的XML和所需的XML。例如。响应必须包含header“Serv”。正文必须包含对象为“person”的xmlHTTP/1.1200OKConnection:Keep-AliveServ:"any-string"Content-Length:0Content-Type:text/xml;charset=UTF-8string-value我如何检查响应是否包含标题“Serv”并包含带有元素人和名称的正文xml 最佳答案
我四处搜索并没有找到另一个这样做的例子,但我无意中发现我能够通过简单地将另一个slice的片段传递给接受slice并返回它的函数来从另一个slice的片段创建一个sliceslice。例子:packagemainimport"fmt"funcmakeSliceFrom(s[]int)[]int{returns}funcmain(){s:=[]int{1,2,3,4,5,6,7,8,9,10}newS:=makeSliceFrom(s[1:7])fmt.Println(newS)}我不是在问这是否有效,因为我知道它有效并且似乎运作良好,我是在问这是否得到支持或有一些我不知道的不可预见的成