gpt4 book ai didi

go - 尝试从文件和目录创建 tar.gz 文件时出现 `write too long` 错误

转载 作者:IT王子 更新时间:2023-10-29 01:26:29 25 4
gpt4 key购买 nike

所以我试图从多个目录和文件创建一个 tar.gz 文件。与以下用法相同的东西:

tar -cvzf sometarfile.tar.gz somedir/ someotherdir/ somefile.json somefile.xml

假设目录中有其他目录。我有这个作为输入:

    paths := []string{
"somedir/",
"someotherdir/",
"somefile.json",
"somefile.xml",
}

并使用这些:

    func TarFilesDirs(paths []string, tarFilePath string ) error {
// set up the output file
file, err := os.Create(tarFilePath)
if err != nil {
return err
}

defer file.Close()
// set up the gzip writer
gz := gzip.NewWriter(file)
defer gz.Close()

tw := tar.NewWriter(gz)
defer tw.Close()

// add each file/dir as needed into the current tar archive
for _,i := range paths {
if err := tarit(i, tw); err != nil {
return err
}
}

return nil
}

func tarit(source string, tw *tar.Writer) error {
info, err := os.Stat(source)
if err != nil {
return nil
}

var baseDir string
if info.IsDir() {
baseDir = filepath.Base(source)
}

return filepath.Walk(source,
func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}

header, err := tar.FileInfoHeader(info, info.Name())
if err != nil {
return err
}

if baseDir != "" {
header.Name = filepath.Join(baseDir, strings.TrimPrefix(path, source))
}

if err := tw.WriteHeader(header); err != nil {
return err
}

if info.IsDir() {
return nil
}

file, err := os.Open(path)
if err != nil {
return err
}

defer file.Close()

_, err = io.Copy(tw, file)
if err != nil {
log.Println("failing here")
return err
}

return err
})
}

问题:如果目录很大,我会得到:

archive/tar: write too long

错误,当我删除它时一切正常。

用完了想法,并为此浪费了很多时间试图找到解决方案......

有什么想法吗?

谢谢

最佳答案

在仔细查看 tar.FileInfoHeader 文档之前,我遇到了类似的问题:

FileInfoHeader creates a partially-populated Header from fi. If fi describes a symlink, FileInfoHeader records link as the link target. If fi describes a directory, a slash is appended to the name. Because os.FileInfo's Name method returns only the base name of the file it describes, it may be necessary to modify the Name field of the returned header to provide the full path name of the file.

本质上,FileInfoHeader 不能保证在您使用 WriteHeader 写入之前填写所有 header 字段,如果您查看实现,Size 字段仅设置在 regular 上。文件。您的代码片段似乎只处理目录,这意味着如果您遇到任何其他非常规文件,您将写入大小为零的 header ,然后尝试将磁盘上可能非零大小的特殊文件复制到 tar 中。 Go 返回 ErrWriteTooLong 以阻止您创建损坏的 tar。

我想到了这个,从那以后就再也没有遇到过这个问题。

    if err := filepath.Walk(directory, func(path string, info os.FileInfo, err error) error {
if err != nil {
return check(err)
}

var link string
if info.Mode()&os.ModeSymlink == os.ModeSymlink {
if link, err = os.Readlink(path); err != nil {
return check(err)
}
}

header, err := tar.FileInfoHeader(info, link)
if err != nil {
return check(err)
}

header.Name = filepath.Join(baseDir, strings.TrimPrefix(path, directory))
if err = tw.WriteHeader(header); err != nil {
return check(err)
}

if !info.Mode().IsRegular() { //nothing more to do for non-regular
return nil
}

fh, err := os.Open(path)
if err != nil {
return check(err)
}
defer fh.Close()

if _, err = io.CopyBuffer(tw, fh, buf); err != nil {
return check(err)
}
return nil
})

关于go - 尝试从文件和目录创建 tar.gz 文件时出现 `write too long` 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38454850/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com