我实现了文件操作功能,并且我注意到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);
所有这些方法都有效,但是我不知道何时应使用它们?从性能和可靠性的角度来看,每种方法的优缺点分别是什么?当我不得不优先使用一种技术而不是另一种技术时,是否有任何特定情况?
我们可以将您的四种方法分为两种类型:
File.renameTo()
Files.move()
首先,请注意,File它没有复制方法,因此在谈论复制时,对于内置的标准库方法只有一个选项。
File
另请注意,重命名时“自行完成工作”非常不好- 您将复制整个文件,然后删除旧文件。这不是一个好的或有效的方法。在大多数情况下,在同一个文件系统中重命名/移动只需要更改文件元数据而不实际接触内容,因此使用标准库确实要好得多。
因此,您有两种情况:
重命名
这些选项实际上使用File.renameTo()或Files.move()。使用流和复制数据毫无意义。
File是过时的课程。它实际上不应该再使用了。为什么有一个很好的解释,可以概括为以下事实:File当任何标准方法都失败时,它不会为您提供任何信息,而Files当这种情况发生时,它会为您提供非常准确的异常。
Files
复制中
您有两种选择-使用Files.copy()或“自己动手”方法之一。
Files.copy()
到目前为止,如果要复制的是实际文件,则选择应为Files.copy()。无需重新发明轮子。它完全符合您的要求,并且有据可查,因此您不太可能偶然引入错误。是的,它非常有效。
Files.copy()依靠底层的“提供者”来进行操作。这意味着有专门的供应商(或操作系统)特定的类来执行对该文件系统最有效的操作。无论是Linux文件系统还是Windows文件系统,副本都将为此进行优化。甚至还有针对特殊情况的提供程序,例如zip文件,因此您可以使用Files.copy()- 复制zip,jar或war文件中的文件-如果尝试“自己动手”方法,则要复杂得多。
此外,Files.copy()检查许多在编写“自己的”副本时可能会忘记的事情。例如,您还记得检查过要读取的文件和要写入的文件是否不是同一文件吗?可能会造成严重的麻烦。Files.copy()可以。它检查权限,检查副本的目标是否是目录,依此类推。因此非常可靠。
那么,为什么您可以选择“自己做”呢?因为好,Java是一种通用语言。您可以选择读取文件,也 可以 选择写入文件,因此 可以 编写自己的“复制”方法。那并不意味着你应该。
请注意,在“方法3”中,“源”文件实际上不是文件!它是由Image URI产生的,这意味着它可能是网络来源。当您的源文件不是文件,而是基于套接字,数据库BLOB,Web服务器请求等的流或通道时,您将无法真正使用Files.copy()。这是您需要编写自己的代码的地方。
实际上,Files还有从文件复制到OutputStream或从复制到文件的选项InputStream,因此,如果副本的一侧是流,另一侧是文件,则可以使用该选项。这将是可读,安全的,并抛出有意义的异常。
OutputStream
InputStream
因此,编写您自己的副本: