Golang创建可能已损坏的文件

时间:2018-02-06 19:20:00

标签: go

我使用以下代码将YAML内容写入文件, 我们在java中有一个旧工具完全相同,现在我们正在构建新工具,它将在Golang中执行相同

使用我使用的内容创建文件

err := ioutil.WriteFile(tmpDirPath, fileContent, 0777)

我不会从此过程中收到任何错误

我能够看到文件内容,看起来不错(与旧工具中创建的文件完全一样)我们有一个无法读取文件的内部工具。错误是:

  

检索存档条目时出错

我检查内容(使用文件差异),我看到它完全相同(来自java和Go工具),我真的很沮丧:(因为我不知道如何继续,也许文件已损坏。 我也尝试过使用file.Mode = 0644并且它没有帮助。

I've Mac and if I can run some checks with command line or other tool to see the diffrent  between the files or maybe between the zip's, (which is created by the old and the new tool) please let me know what to do ...

顺便说一下,在我创建了文件之后,我正在压缩文件并将其提供给内部工具以便使用它。

如果它需要的邮政编码可以帮助识别问题,我也可以在需要时分享

要创建文件所在的目录,我使用

func CreateDirIfNotExist(dir string) {
    if _, err := os.Stat(dir); os.IsNotExist(err) {
        err := os.MkdirAll(dir, 0777)
        if err != nil {
            panic(err)
        }
    }
}

在我完成处理后压缩我使用的所有内容:

func Zipit(params ...string) error {
    zipfile, err := os.Create(params[1])
    if err != nil {
        return err
    }
    defer zipfile.Close()

    archive := zip.NewWriter(zipfile)
    defer archive.Close()

    info, err := os.Stat(params[0])
    if err != nil {
        return nil
    }

    var baseDir string
    if info.IsDir(); len(params) > 2 {
        baseDir = params[2]
    } else {
        baseDir = filepath.Base(params[0])

    }

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

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

        if baseDir != "" {
            header.Name = filepath.Join(strings.TrimPrefix(path, params[0]))
        }

        if info.IsDir() {
            header.Name += "/"
        } else {
            header.Method = zip.Deflate
        }

        writer, err := archive.CreateHeader(header)
        if 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(writer, file)
        return err
    })

    return err
}

更新

我的 MAC

中包含此文件夹

我需要在go上构建它,我可以在Mac上将其解压缩而不会出错 我尝试了两种工具,但我得到了不同的错误。

我使用上面的代码来压缩它的内容,我知道在命令行中解压缩时没有错误,但我们的工具无法读取它... 我在邮政编码上做错了什么? (我需要它没有基础dir压缩)

使用mac默认存档工具和其他工具

enter image description here

[![在此处输入图像说明] [2]] [2]

更新2

根据要求,这是我的整个程序,在完成此过程后成功压缩文件夹但是使用MAC工具无法解压缩它们,请参阅上面的错误以及两个不同的工具,这不会发生(使用mac工具)其他zip文件...

package main

import (
    "archive/zip"
    "fmt"
    "io"
    "log"
    "os"
    "os/exec"
    "path/filepath"
    "strings"
    "bufio"
    "unicode/utf8"
)

func Zipit(params ...string) error {
    zipfile, err := os.Create(params[1])
    if err != nil {
        return err
    }
    defer zipfile.Close()

    archive := zip.NewWriter(zipfile)
    defer archive.Close()

    info, err := os.Stat(params[0])
    if err != nil {
        return err
    }

    var baseDir string
    if info.IsDir(); len(params) > 2 {
        baseDir = params[2]
    } else {
        baseDir = filepath.Base(params[0])
    }

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

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

        fmt.Printf("header: %#v\n", header)

        if baseDir != "" {
            header.Name = filepath.Join(strings.TrimPrefix(path, params[0]))
        }

        if info.IsDir() {
            header.Name += "/"
        } else {
            header.Method = zip.Deflate
        }

        writer, err := archive.CreateHeader(header)
        if 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(writer, file)
        return err
    })

    return err
}

func CreateDirIfNotExist(dir string) {
    if _, err := os.Stat(dir); os.IsNotExist(err) {
        err := os.MkdirAll(dir, 0777)
        if err != nil {
            panic(err)
        }
    }
}

func main() {
    archiveName := "ui5.pre.zip"
    fixedArchiveName := "ui5.zip"

    cmdParams := [][]string{
        {"./ui5", "npm", "install"},
    }

    for _, cp := range cmdParams {
        log.Printf("[INFO] - Starting %s in folder %s...", cp[1:], cp[0])
        cmd := exec.Command(cp[1], cp[2:]...)
        cmd.Dir = cp[0]
        // Wait to finish, get output:

        stdout, err := cmd.StdoutPipe()
        if err != nil {
            log.Panic("%s cmd.StdoutPipe() error: %v\n", cp[1:], err)

        }

        // Start command:
        cmd.Start()

        // Stream the execution of the current command
        scanner := bufio.NewScanner(stdout)
        scanner.Split(bufio.ScanRunes)
        oneRune := make([]byte, utf8.UTFMax)
        for {
            count, err := stdout.Read(oneRune)
            if err != nil {
                break
            }
            fmt.Printf("%s", oneRune[:count])
        }
        log.Println()

        // Get execution success or failure:
        if err := cmd.Wait(); err != nil {
            log.Panic("Error running %s: %v\n", cp[1:], err)

        }
        log.Println("Finished %s", cp[1:])

    }

    if err := Zipit("ui5", "ui5.pre.zip"); err != nil {
        fmt.Println(err)
    }

    if err := exec.Command("zip", "-F", archiveName, "--out", "./"+fixedArchiveName).Run(); err != nil {
        fmt.Println(err)
    }


}

2 个答案:

答案 0 :(得分:2)

问题与https://groups.google.com/forum/#!topic/golang-nuts/0iae5Ng-I-0讨论的相同,取决​​于使用Go archive / go的ZIP64格式。

建议使用Go包装器来解决Java的ZipInputStream https://github.com/30x/zipper

<强>更新 首先,致电

go get github.com/30x/zipper

加载拉链包。

然后尝试使用此版本的Zipit函数来检查解决方案:

import "github.com/30x/zipper"
......
func Zipit(params ...string) error {
    return zipper.Archive(params[0], params[1], zipper.Options{
        ExcludeBaseDir: false, // or true 
    })
}

或尝试修复存​​档创建的Zipit函数(如问题中所示),使其与ZipInputStream兼容。在项目中调用zipper版本函数调用下的zipper.Process函数:

archiveName := "archive.zip" // example code, using yours

err := Zipit(tmpDirPath, archiveName)
if err!=nil {
    return err
}
err := zipper.Process(archiveName, archiveName)
if err!=nil {
    return err
}

第二个版本来修复存档 - 使用带有-F:

选项的zip
archiveName := "ui5.pre.zip" 
fixedArchiveName := "ui5.zip" 

if err := Zipit("ui5", archiveName); err != nil { 
    fmt.Println(err) 
} 

if err := exec.Command("zip", "-F", archiveName, "--out", fixedArchiveName).Run(); err != nil { 
    fmt.Println(err) 
} 

聊天对话的结果。 问题分为两部分。

第一部分取决于存档项目的文件信息。路径必须是相对的,但不是绝对的。文件信息标题名称需要修剪&#39; /&#39;在前缀。

需要修复两段代码。

首先:

var baseDir string
if info.IsDir(); len(params) > 2 {
    baseDir = params[2]
} else {
    baseDir = filepath.Base(params[0])
}
// add the line:
if len(baseDir)>0 {
    baseDir += "/" // add a suffix to trim it in a file name
}

第二

if baseDir != "" {
    header.Name = filepath.Join(strings.TrimPrefix(path, baseDir)) // using baseDir to trim but not params[0]
}

第二部分取决于添加到存档的目录。

在构建存档时完全跳过目录以获得与Java工具相同的结果。

filepath.Walk(params[0], func(path string, info os.FileInfo, err error) error {
    if err != nil {
        return err
    }
    // move up this piece of code
    if info.IsDir() {
        return nil
    }

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

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

    // simplify code - just define a method 
    //if info.IsDir() {
    //  header.Name += "/"
    //} else {
    header.Method = zip.Deflate
    //}

    writer, err := archive.CreateHeader(header)
    if err != nil {
        return err
    }
    // too late - directory is already in the archive
    //if info.IsDir() {
    //  return nil
    //}

答案 1 :(得分:1)

首先,文件不可能相同,解释程序也不可能给出不同的结果。您没有在描述中写下整个历史记录。

  1. 如何检查文件是否已损坏?
  2. 答案在内部工具中。您应该改进其调试消息:&#34;检索存档条目时出错&#34;。什么错误?调试旧工具。并且它建议问题出在zip文件中,而不是json文件。

    1. 我应该尝试使用其他API进行检查吗?如果是,哪个?
    2. 是的,手动解压缩两个文件并区分输出。

      1. 还有其他方向吗?
      2. 阅读旧java工具的代码。