为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
ibeautiful 2023-03-07 10:00:43
下面我有一段代码,它收集了一些 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 1gzw, _ := gzip.NewWriterLevel(w, 1)defer gzw.Close()// Create new tar writertw := 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 tarfp, err := os.Open(file_path)if err != nil {    log.Printf("Error: %v", err)}defer fp.Close()file_name := file[1]+file_extinfo, 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_nametw.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 filegzr, 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 行与原始文件相同。不知何故,最后一点被剪掉了
查看完整描述

1 回答

?
桃花长相依

TA贡献1860条经验 获得超8个赞

问题似乎是您正在根据压缩的原始文件设置文件信息标头。特别是,它是导致问题的大小 - 如果您尝试写入超过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)

}


查看完整回答
反对 回复 2023-03-07
  • 1 回答
  • 0 关注
  • 115 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号