2013-02-10 37 views
3

我有一些代码从一个文件复制到一个TCP套接字(如FTP服务器),并希望能够中止这个副本,如果需要的话。如何停止io.CopyN

我只是使用io.CopyN(套接字,文件,大小),并不能看到一种方式来表示中止。有任何想法吗?

回答

3

CopyN尽量复制N个字节。如果您希望复制少于N个字节,则首先不要使用CopyN。我可能会将原始代码改为类似(未经测试的代码):

func copyUpToN(dst Writer, src Reader, n int64, signal chan int) (written int64, err error) { 
    buf := make([]byte, 32*1024) 
    for written < n { 
     select { 
     default: 
     case <-signal: 
      return 0, fmt.Errorf("Aborted") // or whatever 
     } 

     l := len(buf) 
     if d := n - written; d < int64(l) { 
      l = int(d) 
     } 
     nr, er := src.Read(buf[0:l]) 
     if nr > 0 { 
      nw, ew := dst.Write(buf[0:nr]) 
      if nw > 0 { 
       written += int64(nw) 
      } 
      if ew != nil { 
       err = ew 
       break 
      } 
      if nr != nw { 
       err = io.ErrShortWrite 
       break 
      } 
     } 
     if er != nil { 
      err = er 
      break 
     } 
    } 
    return written, err 
} 
+0

希望copyN会做大块,不是一次全部。 – Lodle 2013-02-10 11:46:10

+0

32 * 1024是上述代码中的(可调整)块大小。 – zzzz 2013-02-10 12:12:19

4

刚刚关闭输入文件怎么样?然后io.CopyN将返回一个错误并中止。

这里是一个演示(如果不是在Linux上的变化/dev/zero & /dev/null您的操作系统相当于运行!)

package main 

import (
    "fmt" 
    "io" 
    "log" 
    "os" 
    "time" 
) 

func main() { 
    in, err := os.Open("/dev/zero") 
    if err != nil { 
     log.Fatal(err) 
    } 

    out, err := os.Create("/dev/null") 
    if err != nil { 
     log.Fatal(err) 
    } 

    go func() { 
     time.Sleep(time.Second) 
     in.Close() 
    }() 

    written, err := io.CopyN(out, in, 1E12) 
    fmt.Printf("%d bytes written with error %s\n", written, err) 
} 

在运行时会打印出类似这样

9756147712 bytes written with error read /dev/zero: bad file descriptor