2015-05-21 34 views
6

Mam następującą funkcję do kopiowania pliku (io.Reader faktycznie) do lokalizacji docelowego ciągu. Wydaje się jednak, że tylko część pliku jest faktycznie kopiowana, co powoduje uszkodzenie pliku. Co ja robię źle?Jak skopiować plik w Go?

func CopyFile(in io.Reader, dst string) (err error) { 

    // Does file already exist? Skip 
    if _, err := os.Stat(dst); err == nil { 
     return nil 
    } 

    err = nil 

    out, err := os.Create(dst) 
    if err != nil { 
     fmt.Println("Error creating file", err) 
     return 
    } 

    defer func() { 
     cerr := out.Close() 
     if err == nil { 
      err = cerr 
     } 
    }() 


    var bytes int64 
    if bytes, err = io.Copy(out, in); err != nil { 
     fmt.Println("io.Copy error") 
     return 
    } 
    fmt.Println(bytes) 

    err = out.Sync() 
    return 
} 

Używam tego metodą filepath.Walk(dir, visit) przetwarzać pliki w katalogu.

// Process each matching file on our walk down the filesystem 
func visit(path string, f os.FileInfo, err error) error { 

    if reader, err := os.Open(path); err == nil { 
     defer reader.Close() 

     // http://golang.org/pkg/os/#FileInfo 
     statinfo, err := reader.Stat() 

     if err != nil { 
      fmt.Println(err) 
      return nil 
     } 

     fmt.Println() 
     fmt.Println(statinfo.Size()) 

     // Directory exists and is writable 
     err = CopyFile(reader, "/tmp/foo/"+f.Name()) 

     if err != nil { 
      fmt.Println(err) 
     } 

    } else { 
     fmt.Println("Impossible to open the file:", err) 
    } 
} 

Obecny closest question mogłem ma zaakceptowane odpowiedź, która zaleca stosowanie twarde/miękkie linki i nie przerwać, jeśli plik już istnieje.

+1

'io.Copy' zwraca liczbę zapisanych bajtów. Powinieneś to sprawdzić, może to pomoże. –

+1

Twój kod działa również dla mnie. Czy możesz pokazać, w jaki sposób korzystasz z tej funkcji? –

+0

Co zapewnia "in"? Czy widzisz * jakieś * błędy? Czy zły plik już istnieje (w takim wypadku powracasz cicho)? – JimB

Odpowiedz

5
package main 

import (
    "fmt" 
    "io" 
    "os" 
) 

func main() { 
    srcFile, err := os.Open("test.txt") 
    check(err) 
    defer srcFile.Close() 

    destFile, err := os.Create("test_copy.txt") // creates if file doesn't exist 
    check(err) 
    defer destFile.Close() 

    _, err = io.Copy(destFile, srcFile) // check first var for number of bytes copied 
    check(err) 

    err = destFile.Sync() 
    check(err) 
} 

func check(err error) { 
    if err != nil { 
     fmt.Println("Error : %s", err.Error()) 
     os.Exit(1) 
    } 
} 

Ten kod działa dla mnie. Sprawdź liczbę bajtów skopiowanych z wartością zwracaną z io.Copy.

+0

Dla jasności: Należy zawsze sprawdzać err przed użyciem odroczenia. –

+1

Dobrze. Dokonano zmian. – apoorvam