首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用流复制文件

使用流复制文件
EN

Stack Overflow用户
提问于 2011-10-13 10:06:29
回答 3查看 1K关注 0票数 0

以下示例展示了如何使用streams复制文件。

代码语言:javascript
复制
private void copyWithStreams(File aSourceFile, File aTargetFile, boolean aAppend) {
log("Copying files with streams.");
ensureTargetDirectoryExists(aTargetFile.getParentFile());
InputStream inStream = null;
OutputStream outStream = null;
try{
  try {
    byte[] bucket = new byte[32*1024];
    inStream = new BufferedInputStream(new FileInputStream(aSourceFile));
    outStream = new BufferedOutputStream(new FileOutputStream(aTargetFile, aAppend));
    int bytesRead = 0;
    while(bytesRead != -1){
      bytesRead = inStream.read(bucket); //-1, 0, or more
      if(bytesRead > 0){
        outStream.write(bucket, 0, bytesRead);
      }
    }
  }
  finally {
    if (inStream != null) inStream.close();
    if (outStream != null) outStream.close();
  }
}
catch (FileNotFoundException ex){
  log("File not found: " + ex);
}
catch (IOException ex){
  log(ex);
}
}

private void ensureTargetDirectoryExists(File aTargetDir){
if(!aTargetDir.exists()){
  aTargetDir.mkdirs();
}
}
private static void log(Object aThing){
  System.out.println(String.valueOf(aThing));
}

对于上面的代码片段,我对以下四点感到困惑:

1) Bucket的分配方式为: byte[] bucket =新字节32*1024,大小是否有选择标准,如32*1024

2)为什么它必须在这里“捕捉”?在编写程序时有没有包含catch的规则?

3)我也不太清楚try在这里的用法。似乎作者在这个程序中使用了嵌套的try。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-10-13 11:01:38

1)没有标准来定义字节数组的大小。在给定的代码中,它使用了32k字节,但您可以使用任何值。字节数组的大小和文件的大小决定了您将读取文件的次数,较大的缓冲区会导致较少的读取调用,但如果您正在处理小文件,则不是必需的。

2)每当在Java中使用可能抛出异常的方法时,都需要捕获该异常并对其执行某些操作。您可以在代码中处理异常(通常打印堆栈跟踪以进行调试),也可以抛出它,这意味着当有人使用您的代码时,需要捕获您的代码的异常。

3)他所做的是捕获两个可能的异常,并指定哪个异常会发生。因为FileNotFoundException扩展了IOException,他可以简单地使用一次尝试,并且只捕获IOException,所以他以这种方式编码,以知道IOExceptionFileNotFoundException还是任何其他IOException。就我个人而言,我不会以作者的方式编写代码,它不容易阅读。

也许重写代码会让你更容易理解其中的尝试和陷阱:

代码语言:javascript
复制
        System.out.println("Copying files with streams.");
    InputStream inStream = null;
    OutputStream outStream = null;
    try {
        inStream = new BufferedInputStream(new FileInputStream(aSourceFile));
        outStream = new BufferedOutputStream(new FileOutputStream(aTargetFile, aAppend));
    } catch (FileNotFoundException ex){
        // TODO Handle FileNotFoundException
        ex.printStackTrace();
    }
    try {
        byte[] bucket = new byte[32*1024];
        int bytesRead = 0;
        while(bytesRead != -1){
          bytesRead = inStream.read(bucket); //-1, 0, or more
          outStream.write(bucket, 0, bytesRead);
        }
    } catch (IOException ex){
        // TODO Handle IOException
        ex.printStackTrace();
    } finally {
        try {
            if (inStream != null) inStream.close();
            if (outStream != null) outStream.close();
        } catch (IOException ex){
            // TODO Handle IOException
            ex.printStackTrace();
        }
    }

它做同样的事情。

票数 0
EN

Stack Overflow用户

发布于 2011-10-13 10:22:33

  1. 我们假设你不能很好地将整个文件放入内存,所以我们一次选择一小块,处理它,然后抓取下一块。在本例中,我们使用的是32千字节。您可以使用更多或更少,但在硬盘扇区大小(通常为4kb)的(小)倍数中工作将更有效率,并导致较少的IO操作。
  2. 如果您抛出异常,或调用抛出异常的方法,则必须处理它。您可以使用try{}catch{} (或finally{})语句块将其包围,也可以向上抛出异常,以调用此方法。在本例中,您有一条try{}语句,因此伴随的statements.
  3. The作者catchfinally做了一些不必要的事情:他本可以使用一个try{},然后将finally{}块放在catch{}语句之后。相反,内部try{}在执行finally{}块之后将异常传递给外部try{}。在此之后,将根据抛出的Exception类型激活catch{}块。
票数 1
EN

Stack Overflow用户

发布于 2011-10-13 10:23:55

1) 32 * 1024等于32 an,我认为这是格式化NTFS卷时的默认分配单位大小。通过匹配底层文件系统,可能会有一些性能提升,因为如果没有正确缓存,就不会重写磁盘的扇区。缓冲区越大,操作通常越流畅。不过,你不能在较小的设备上使用巨大的缓冲区(尽管手机的内存越来越大)

2)这里的陷阱可能非常烦人。如果您请求复制文件,而原始文件并不存在,那么您得到的只是一个日志,调用此方法的程序可能会假定它是有效的。此方法可能会重新抛出异常,调用程序将处理找不到的文件。IO问题也是如此。

3)最后是很重要的,因为无论发生什么,你都要确保资源是关闭的。如果在记录其他异常后关闭资源,那么使用嵌套的try语句并不会带来运行时的好处。(次要问题,如果在关闭inStream时发生异常抛出,outStream将不会关闭,任何其他异常都将丢失)。程序员可能会认为将close语句放在读取和写入附近看起来更干净,但它们很可能被移到外部try

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7748657

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档