我实现了一个文件操作功能,我注意到Java提供了多种复制和移动文件的技术。下面您可以找到代码片段,简要描述了这些方法:
方法#1:
File from = new File(src.getPath());
File to = new File(dst.getPath());
from.renameTo(to);
方法#2:
FileChannel inChannel = new FileInputStream(src).getChannel();
FileChannel outChannel = new FileOutputStream(dst).getChannel();
inChannel.transferTo(0, inChannel.size(), outChannel);
方法#3:
InputStream in = getContentResolver().openInputStream(selectedImageUri);
OutputStream out = new FileOutputStream("/sdcard/wallpapers/" + wall);
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
方法#4:
import static java.nio.file.StandardCopyOption.*;
Files.copy(source, target, REPLACE_EXISTING);
所有这些方法都有效,但我不能掌握什么时候应该使用它们。这些方法的优缺点是什么,特别是从性能和可靠性的角度来看?当我必须选择一种技术而不是另一种技术时,有没有什么特定的场景?
发布于 2015-06-30 04:32:16
我们可以将你的四种方法分为两类:
File.renameTo()
和File.renameTo()
)-通过将字节从源复制到目标。首先,请注意File
没有copy方法,所以当您谈论copy时,您只有一个内置的标准库方法可供选择。
还请注意,当重命名将非常糟糕时,“自己完成工作”-您将复制整个文件,然后删除旧文件。不是一个好的或有效的方法。在大多数情况下,在同一文件系统中重命名/移动只需要更改文件元数据,而不需要实际接触内容,因此使用标准库确实要好得多。
所以你有两个案例:
重命名
这些选项实际上是使用File.renameTo()
或Files.move()
。使用streams和复制数据没有意义。
File
是一个过时的类。它真的不应该再使用了。有一个很好的explanation why,它总结了这样一个事实:当File
的任何标准方法失败时,它不会向您提供任何信息,而Files
在发生这种情况时会为您提供非常准确的异常。
复制
您有两个选择--要么使用Files.copy()
,要么使用“自己动手”的方法。
到目前为止,如果您正在复制的是实际的文件,那么您的选择应该是Files.copy()
。没有必要重新发明轮子。它做的正是你想要的,有很好的文档记录,你不太可能意外地引入错误。是的,这是非常有效的。
Files.copy()
的操作依赖于底层的“提供者”。这意味着有专门的供应商(或操作系统)特定的类来执行对该文件系统最有效的操作。无论是Linux文件系统还是Windows文件系统,副本都会针对它进行优化。甚至有针对特殊情况的提供程序,例如压缩文件,因此您可以使用Files.copy()
复制压缩文件、jar文件或war文件中的文件-如果您尝试“自己做”方法,这将复杂得多。
此外,Files.copy()
检查了很多你在写“你自己的”副本时可能会忘记的东西。例如,您是否记得检查您正在读取的文件和正在写入的文件是否不是同一个文件?这可能会带来严重的麻烦。Files.copy()
做到了。它检查权限,检查副本的目标是否是目录,等等。所以它非常可靠。
那么为什么你可以选择做“你自己的”呢?因为Java是一种通用语言。您可以选择从文件读取,也可以选择写入文件,因此您可以编写自己的“复制”方法。但这并不意味着你应该这么做。
注意,在你的“方法#3”中,“源”文件实际上并不是一个文件!它是由Image URI生成的,这意味着它可能是一个网络来源。如果源文件不是文件,而是基于套接字、数据库BLOB、web服务器请求等的流或通道,则不能真正使用Files.copy()
。这就是您需要编写自己的代码的地方。
实际上,Files
还提供了从文件复制到OutputStream
或从InputStream
复制到文件的选项,因此如果副本的一端是流,另一端是文件,则可以使用该选项。它将是可读的,安全的,并抛出有意义的异常。
所以写你自己的副本:
https://stackoverflow.com/questions/31123067
复制相似问题