2015-05-21 4 views
6

У меня есть следующая функция, чтобы скопировать файл (на самом деле io.Reader) в место назначения строки. Однако, похоже, что только часть файла фактически скопирована, что приводит к поврежденному файлу. Что я делаю не так?Как вы копируете файл в 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 
} 

Я использую это с помощью метода filepath.Walk(dir, visit) для обработки файлов в директории.

// 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) 
    } 
} 

В настоящее время closest question я мог есть общепринятый ответ, который рекомендует жесткий/используя символьные ссылки и не прервать, если файл уже существует.

+1

'io.Copy' возвращает количество записанных байтов. Вы должны это проверить, может быть, это поможет. –

+1

Кроме того, ваш код работает для меня. Можете ли вы показать, как вы используете эту функцию? –

+0

Что вы предоставляете 'in'? Вы видите * любые ошибки? Имеет ли плохой файл уже существующий (в этом случае вы возвращаетесь молча)? – JimB

ответ

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) 
    } 
} 

Этот код работает для меня. Проверьте количество байтов, скопированных с возвращаемым значением от io.Copy.

+0

Просто, чтобы быть ясным: всегда нужно проверять ошибки перед использованием отсрочки. –

+1

Справа. Сделаны изменения. – apoorvam

Смежные вопросы