将 .gz 文件添加到 tar.gz 文件,但在添加之前解码 gz。输出文件被剪裁(损坏)

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


我想将 PDF 添加到tar.gz文件中,但在添加它们之前,它们需要解压缩 (gzip)。不想以tar.gz充满pdf.gz文件的方式结束


需要在不将整个文件读入内存的情况下解压它。中的 PDF 文件tar.gz被剪切和损坏。当我将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)

更新

从评论中得到建议,但现在无法打开 tar 中的 PDF 文件。tar.gz 文件已创建并可以打开,但里面的 PDF 文件已损坏


已尝试将输出文件与tar.gz原始 PDF 进行比较。损坏的文件似乎缺少文件的最后一位。


在一个示例中,原始文件有 498 行,而损坏的只有 425 行。但看起来 425 行与原始文件相同。不知何故,最后一点被剪掉了


ibeautiful
浏览 116回答 1
1回答

桃花长相依

问题似乎是您正在根据压缩的原始文件设置文件信息标头。特别是,它是导致问题的大小 - 如果您尝试写入超过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 tarfp, 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 fileheader := &tar.Header{    Name: file_name,    Mode: 0600,    Size: int64(len(data)),}// Write header to the tarif err = tw.WriteHeader(header); err != nil {    log.Printf("Error: %v", err)}// Write the file content to the tarif _, err = tw.Write(data); err != nil {    log.Printf("Error: %v", err)}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go