简介
Files类是java.nio.file包的另一个主要入口点。该类提供了一组丰富的静态方法,用于读取,写入和操作文件和目录。Files方法适用于Path对象的实例。在进行其余部分之前,您应该熟悉以下常见概念:释放系统资源、捕捉异常、可变参数、原子操作、方法链、什么是Glob
释放系统资源
此API中使用的许多资源(如流或通道)实现或扩展了java.io.Closeable接口。关闭资源的要求是必须调用close方法以在不再需要时释放资源。忽略关闭资源可能会对应用程序的性能产生负面影响。下一节中描述的try-with-resources语句为您处理此步骤。
捕捉异常
使用文件I / O,一个很现实很常见的意外是:当一个文件被期待时,它存在(或不存在),该程序无法访问该文件系统,默认文件系统实现不支持特定功能,等等。可能会遇到许多错误。
访问文件系统的所有方法都可能会导致IOException异常。最好的做法是通过将这些方法嵌入到Java SE 7版本中引入的try-with-resources语句中来捕获这些异常。try-with-resources语句的优点在于,当不再需要时,编译器会自动生成代码以关闭资源。以下代码显示了如何显示:
Charset charset = Charset.forName("US-ASCII");
String s = ...;
try (BufferedWriter writer = Files.newBufferedWriter(file, charset)) {
writer.write(s, 0, s.length());
} catch (IOException x) {
System.err.format("IOException: %s%n", x);
}
或者,您可以将文件I / O方法嵌入到try块中,然后捕获catch块中的任何异常。如果你的代码打开了任何流或通道,你应该在一个finally块中关闭它们。前面的例子看起来像以下使用try-catch-finally方法:Charset charset = Charset.forName("US-ASCII");
String s = ...;
BufferedWriter writer = null;
try {
writer = Files.newBufferedWriter(file, charset);
writer.write(s, 0, s.length());
} catch (IOException x) {
System.err.format("IOException: %s%n", x);
} finally {
if (writer != null) writer.close();
}
除了IOException之外,很多具体的异常扩展了FileSystemException。这个类有一些有用的方法返回涉及的文件(getFile),详细的消息字符串(getMessage)文件系统操作失败(getReason)和“其他”文件涉及的原因(如果有的话)(getOtherFile)
以下代码片段显示了如何使用getFile方法
try (...) {
...
} catch (NoSuchFileException x) {
System.err.format("%s does not exist\n", x.getFile());
}
为了清楚起见,本课程中的文件I / O示例可能不会显示异常处理,但是您的代码应该始终包含它可变参数
当指定标志时,几个Files方法接受任意数量的参数。例如,在以下方法签名中,CopyOption参数之后的椭圆符号表示该方法接受可变数量的参数或变量,因为它们通常称为:
Path Files.move(Path, Path, CopyOption...)
就像move的例子,可以向下面一样被调用:
import static java.nio.file.StandardCopyOption.*;
Path source = ...;
Path target = ...;
Files.move(source,
target,
REPLACE_EXISTING,
ATOMIC_MOVE);
原子操作
几个Files方法,比如move,在一些文件系统中可以进行原子操作
一个原子操作的含义是:操作不能被中断或者部分执行。 不管是进入操作失败还是其他操作失败,当您有多个进程在文件系统的相同区域运行时,这很重要,您需要确保每个进程访问完整的文件。
方法链
很多文件IO方法都支持方法链的概念
你可以首先调用一个方法返回一个对象,然后立刻在这个对象上调用另外一个方法,然后返回另一个操作对象,以此类推。很多IO例子使用下面的技术:
String value = Charset.defaultCharset().decode(buf).toString();
UserPrincipal group =
file.getFileSystem().getUserPrincipalLookupService().
lookupPrincipalByName("me");
这个技术提供了一段紧凑的代码,使你可以避免声明你不需要的临时变量
什么是 Glob?
在File类中,有两个方法支持接收全局参数,但是,什么是全局?
您可以使用glob语法指定模式匹配行为
glob模式被指定为字符串,并与其他字符串匹配,例如目录或文件名。 Glob语法遵循几个简单的规则:
1,一个星号*匹配任意数量的字符(包括无)。
2,两个星号**,像*一样工作,但跨越目录边界。这种语法通常用于匹配完整的路径。
3,问号,匹配一个字符。
4,大括号指定子模式的集合。例如: {太阳,月亮,星星}匹配“太阳”,“月亮”或“星星”。 {temp *,tmp *}匹配以“temp”或“tmp”开头的所有字符串。
5,方括号传送一组单个字符,或者使用连字符( - )时,会显示一系列字符。例如: [aeiou]匹配任何小写的元音。 [0-9]匹配任何数字。 [A-Z]匹配任何大写字母。 [a-z,A-Z]匹配任何大写或小写字母。 在方括号内,*,?和\匹配自己。 所有其他角色都与自己匹配
6,要匹配*,?或其他特殊字符,您可以使用反斜杠字符\来将其转义。例如:\\匹配单个反斜杠,\?匹配问号。
以下是glob语法的一些示例:
* .html - 匹配以.html结尾的所有字符串
??? - 匹配三个字母或数字的所有字符串
* [0-9] * - 匹配包含数值的所有字符串
* {htm,html,pdf} - 匹配以.htm,.html或.pdf结尾的任何字符串
a?*。java - 匹配以a开头的任何字符串,后跟至少一个字母或数字,以.java结尾
{foo *,* [0-9] *} - 匹配以foo开头的任何字符串或包含数值的任何字符串
注意:如果您在键盘上键入glob模式,并且包含其中一个特殊字符,则必须将模式置于引号(“*”)中,使用反斜杠(\ *),或使用任何支持的转义机制命令行。
glob语法功能强大且易于使用。但是,如果您的需求不足,您还可以使用正则表达式。有关更多信息,请参阅正则表达式课程。 有关glob sytnax的更多信息,请参阅FileSystem类中的getPathMatcher方法的API规范。