当我压缩 >= 60MB 的 json 文件时,出现数据不足且只有 28MB 可用的错误。
func CreateTarGz(sourceDir, targetFile string) error {
target, err := os.Create(targetFile)
if err != nil {
return err
}
defer target.Close()
gw := gzip.NewWriter(target)
defer gw.Close()
tw := tar.NewWriter(gw)
defer tw.Close()
err = filepath.Walk(sourceDir, func(path string, info fs.FileInfo, err error) error {
if err != nil {
return err
}
// Tạo header cho tệp
header, err := tar.FileInfoHeader(info, "")
if err != nil {
return err
}
header.Name = strings.TrimPrefix(strings.TrimPrefix(path, sourceDir), string(filepath.Separator))
header.Size = info.Size()
if err := tw.WriteHeader(header); err != nil {
return err
}
if info.IsDir() {
return nil
}
// Mở tệp
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
// Sử dụng bộ đệm để đọc tệp
buf := make([]byte, 1024*1024*2)
header.Size = info.Size()
for {
n, err := file.Read(buf)
if err != nil && err != io.EOF {
return err
}
if n == 0 {
break
}
if _, err := tw.Write(buf[:n]); err != nil {
log.Printf("failed to write %d bytes to tar for %s: %v", n, path, err)
return err
}
}
return nil
})
return err
}
我想从一个 json 文件 >= 60mb 的文件夹中压缩一个 tar.gz 文件,如何才能不出错。目前我只能写入28mb,其余的都缺少数据。
👋。正如其他人在评论中指出的那样,您可以使用 os.Copy 来获取 WalkDir 循环内文件的所有字节。 我还注意到您正在尝试手动设置标题的名称和大小,但这已经由以下处理:
header, err := tar.FileInfoHeader(info, "")
尝试手动设置名称和大小也会对循环的第一次迭代(对于 sourceDir)产生负面影响,因为您将 sourceDir 修剪为空字符串,然后用空字符串覆盖标头的名称。
这是我根据您的代码编写的一个最小示例(我也在其中写了自己的评论):
fGzip, err := os.Create("baz.gzip")
if err != nil {
panic(err)
}
defer fGzip.Close()
wGzip := gzip.NewWriter(fGzip)
defer wGzip.Close()
wTar := tar.NewWriter(wGzip)
defer wTar.Close()
err = filepath.Walk("./tmp", func(path string, info fs.FileInfo, err error) error {
if err != nil {
return err
}
// Create header for entry
header, err := tar.FileInfoHeader(info, "")
if err != nil {
return err
}
if err := wTar.WriteHeader(header); err != nil {
return err
}
// Don't try to write dir to Tar
if info.IsDir() {
return nil
}
// Write file to Tar
b, err := os.ReadFile(path)
if err != nil {
return err
}
_, err = wTar.Write(b)
if err != nil {
return err
}
return nil
})
if err != nil {
panic(err)
}
当我在 tmp 文件夹上运行它时:
+ tmp
+ bar
- file1.txt
+ foo
- file2.json
然后运行
tar -tzf baz.gzip
,我得到了预期的结果:
tmp/
bar/
file1.txt
foo/
file2.json