2017-09-12 6 views
0

J'ai testé le code en utilisant io.Pipe pour tarer et gunzip fichiers dans une boule tar, puis dézipper en utilisant l'utilitaire tar. Le code de suivi passe, mais le processus ne cesse de se décompressé l'archivebug en utilisant golang io.pipe pour tar fichiers

erreur: tar: Truncated input file (needed 1050624 bytes, only 0 available) tar: Error exit delayed from previous errors.

Cette question est vraiment me rend fou. Cela fait deux semaines. J'ai vraiment besoin d'aide pour le débogage.

Merci.

ambience développement: go Version go1.9 darwin/amd64

package main 

import (
    "archive/tar" 
    "compress/gzip" 
    "fmt" 
    "io" 
    "log" 
    "os" 
    "path/filepath" 
    "testing" 
) 

func testTarGzipPipe2(t *testing.T) { 
    src := "/path/to/file/folder" 

    pr, pw := io.Pipe() 
    gzipWriter := gzip.NewWriter(pw) 
    defer gzipWriter.Close() 
    tarWriter := tar.NewWriter(gzipWriter) 
    defer tarWriter.Close() 

    status := make(chan bool) 

    go func() { 
     defer pr.Close() 
     // tar to local disk 
     tarFile, err := os.OpenFile("/path/to/tar/ball/test.tar.gz", os.O_RDWR|os.O_CREATE, 0755) 
     if err != nil { 
      log.Fatal(err) 
     } 
     defer tarFile.Close() 
     if _, err := io.Copy(tarFile, pr); err != nil { 
      log.Fatal(err) 
     } 

     status <- true 
    }() 

    err := filepath.Walk(src, 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 
     } 

     // header.Name = strings.TrimPrefix(strings.Replace(path, src, "", -1), string(filepath.Separator)) 

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

     if info.Mode().IsDir() { 
      return nil 
     } 

     fmt.Println(path) 
     f, err := os.Open(path) 
     if err != nil { 
      return err 
     } 
     defer f.Close() 

     if _, err := io.Copy(tarWriter, f); err != nil { 
      return err 
     } 

     return nil 
    }) 

    if err != nil { 
     log.Fatal(err) 
    } 

    pw.Close() 
    <-status 
} 
+2

Quelle est l'erreur? Aussi s'il vous plaît 'Go fmt' le fichier – reticentroot

+0

Non lié: Vous ne devriez pas appeler log.Fatal dans les tests (ou partout où vous prévoyez d'exécuter un' defer'statement), car il empêche tout nettoyage que vous avez l'intention de faire, et peut cacher échec des tests. Il y a un 't.Fatal' qui fait ce que vous voulez. Un fichier tar ne devrait pas être exécutable. Fermez un canal plutôt que d'envoyer une valeur sentinelle comme un signal, ou mieux encore, utilisez un WaitGroup pour attendre les goroutines. – JimB

Répondre

1

Vous fermez le tuyau avant que les appels Fermer différés sur la gzipWriter et tarWriter. Il n'y a pas d'erreur, car vous ne vérifiez pas l'erreur sur l'un de ces appels. Vous devez fermer le tarWriter, puis le gzipWriter, puis le PipeWriter, dans cet ordre.

Cependant, il n'y a aucune raison pour le tube dans ce code, et vous pouvez supprimer le goroutine et la coordination associée si vous écrivez directement dans le fichier.

tarFile, err := os.OpenFile("/tmp/test.tar.gz", os.O_RDWR|os.O_CREATE, 0644) 
if err != nil { 
    log.Fatal(err) 
} 
defer tarFile.Close() 

gzipWriter := gzip.NewWriter(tarFile) 
defer gzipWriter.Close() 
tarWriter := tar.NewWriter(gzipWriter) 
defer tarWriter.Close() 
+0

Une chose importante que j'ai oublié est de fermer l'auteur ouvert dans l'ordre inverse. J'espère que les autres pourraient apprendre de mon erreur. Merci encore @ JimB. – NSTNF

+0

@NSTNF: en fait vous aviez les 'tarWriter.Close()' et 'gzipWriter.Close()' corrects, les appels différés sont exécutés dans l'ordre LIFO. – JimB

+0

Merci. Golang est différent des autres langues. Il faut que le développeur change de mentalité de codage. Je m'efforce de coder correctement et ensuite efficacement. Les auteurs ouverts doivent être fermés dans l'ordre inverse. Cela pourrait être une erreur commune. Serait-il bénéfique pour les autres développeurs de créer un wiki d'erreurs courantes ou d'ajouter quelque chose comme "avertissement: fermer le script tar avant de fermer le script gzip" à la documentation golang correspondante? – NSTNF