下面是我的代码片段,它收集了一些gzip压缩的PDF文件.

我想将PDF添加到tar.gz文件中,但在添加它们之前,需要对它们进行解压缩(Gzip).我不想以一个充满了pdf.gz个文件的tar.gz结尾

需要将其解压缩,而无需将整个文件读取到内存中.tar.gz中的PDF文件被剪裁和损坏.当我比较tar.gz个文件和原始的PDF文件时,除了tar.gz个文件被剪切外,看起来是一样的.每个文件的最后一部分都不见了

// Create new gz writer with compression level 1
gzw, _ := gzip.NewWriterLevel(w, 1)
defer gzw.Close()

// Create new tar writer
tw := tar.NewWriter(gzw)
defer tw.Close()

file_path := "path-to-file.pdf.gz"
file_name := "filename-shown-in-tar.pdf"

// Open file to add to tar
fp, err := os.Open(file_path)
if err != nil {
    log.Printf("Error: %v", err)
}
defer fp.Close()

file_name := file[1]+file_ext

info, err   := fp.Stat()
if err != nil {
    log.Printf("Error: %v", err)
}
header, err := tar.FileInfoHeader(info, file_name)
if err != nil {
    log.Printf("Error: %v", err)
}
header.Name = file_name

tw.WriteHeader(header)

// This part will write the *.pdf.gz files directly to the tar.gz file
// This part works and it's possible to both open the tar.gz file and
// afterwards open the individuel pdf.gz files
//io.Copy(tw, fp)

// This part decode the gz before adding, but it clips the pdf files in
// the tar.gz file
gzr, err := gzip.NewReader(fp)
if err != nil {
    log.Printf("Error: %v", err)
}
defer gzr.Close()
io.Copy(tw, gzr)

update

我从一条 comments 中得到了一个建议,但现在TAR中的PDF文件无法打开.Tar.gz文件已创建并可打开,但其中的PDF文件已损坏

我已try 将tar.gz的输出文件与原始PDF进行比较.看起来损坏的文件丢失了文件的最后一部分.

在一个例子中,原始文件有498行,而损坏的文件只有425行.但它看起来425行与原始的相同.不知怎么的,最后一块被剪掉了

推荐答案

问题似乎是,您正在基于压缩的原始文件设置文件信息头.特别是,导致问题的是大小-如果您try 写入的大小超过标头中Size值所指示的大小,archive/tar.Writer.Write()将返回ErrWriteTooLong-请参见https://github.com/golang/go/blob/d5efd0dd63a8beb5cc57ae7d25f9c60d5dea5c65/src/archive/tar/writer.go#L428-L429

下面这样做应该是可行的,这样就可以对文件进行解压缩和读取,从而确定准确的大小:

// Open file to add to tar
fp, err := os.Open(file_path)
if err != nil {
    log.Printf("Error: %v", err)
}
defer fp.Close()

gzr, _ := gzip.NewReader(fp)
if err != nil {
    panic(err)
}
defer gzr.Close()

data, err := io.ReadAll(gzr)
if err != nil {
    log.Printf("Error: %v", err)
}

// Create tar header for file
header := &tar.Header{
    Name: file_name,
    Mode: 0600,
    Size: int64(len(data)),
}

// Write header to the tar
if err = tw.WriteHeader(header); err != nil {
    log.Printf("Error: %v", err)
}

// Write the file content to the tar
if _, err = tw.Write(data); err != nil {
    log.Printf("Error: %v", err)
}

Go相关问答推荐

Golang regexpp:获取带有右括号的单词

Golang ==错误:OCI运行时创建失败:无法启动容器进程:exec:./" bin:stat./" bin:没有这样的文件或目录:未知

在Uber FX中实现后台进程正常关闭的正确方式是什么?

Go SQLCMD比Windows本机版本慢吗?

golang有int32溢出吗?

如果values.yaml文件中不存在某个属性,如何返回默认的FALSE?

golang regex基于关键字拆分字符串

go-chi: 接受带有反斜杠的 url 路径参数

如何使用 AWS sdk 在 Go 中正确解组 PartiQL 查询的结果?

Go 中带有回调的 MiniDumpWriteDump

如何使用 html/template 在 golang 中运行一个范围内的范围

Golang telegram 机器人

Caddy服务器try 打开端口80而不是8090.

判断不同 go map 类型中的重复键

函数超时和 goroutine 泄漏

在 go 中将运行命令的标准输出发送到其标准输入

K8s 算子读取原始数据

不理解切片和指针

try 执行`go test ./... -v`时,Golang中有没有办法设置标志

如何迭代在泛型函数中传递的片的并集?