操作文件

来源:互联网 发布:c语言按位取反 符号位 编辑:程序博客网 时间:2024/04/27 21:27

Path 和 Files类封装了在用户机器上处理文件系统所需要的所有功能。例如,可以使用Files 类来移除或重命名文件,或者查询文件最后被修改的时间。换句话说,流类关心的是文件的内容,而我们在此处要讨论的类关心的是在磁盘上如何存储文件。

Path 和 Files 是在Java SE7 中新添加进来的类,它们用起来比自JDK1.0 就一直使用的File 类 要方便的多。

Path

Path 表示的是一个目录名序列,其后还可以跟着一个文件名。路径中的第一个部件可以是根部件,例如/或C:\,而允许访问的根部件取决于文件系统。以根部件开始的路径是绝对路径;否则就是相对路径。

Path absolut = Paths.get("G:\\04JavaIO","hello.txt");Path relative = Paths.get("04JavaIO","hello.txt");

静态的Paths.get 方法接受一个或多个字符串,并将它们用默认文件系统的路径分隔符连接起来。然后它解析连接起来的结果,如果其表示的不是给定文件系统中的合法路径,那么就抛出InvalidPathException 异常。这个连接起来的结果就是一个Path 对象。
路径不必对应着某个实际存在的文件,它仅仅只是一个抽象的名字序列。当你想要创建文件时,首先要创建一个路径,然后才调用方法去创建对应的文件。

组合或解析路径

调用p.resolve(q) 将按照下面规则返回一个路径:

  • 如果q 是绝对路径,则结果就是q。
  • 否则,根据文件系统的规则,将“p后面跟着q”作为结果。

    resolveSibling方法,通过解析指定路径的父路径产生其兄弟路径。例如,如果workPath 是 \opt\myapp\work,那么下面的调用
    Path temPath = workPath.resolveSibling("temp");
    将创建\otp\myapp\temp。

relativize方法,即调用p.relativize(r) 将产生路径q,对q进行解析会产生r。例如,以“/home/cay” 为目标对”/home/fred/myprog” 进行相对化操作,会产生“../fred/myprog”,其中,我们假设 .. 表示文件系统中的父目录。
toAbsolutePath 方法将产生给定路径的绝对路径,该绝对路径从根部件开始。

读写文件

Files 类可以使得普通文件操作变得快捷。例如,可以用下面的方式很容易地读取文件的所有内容:
byte[] bytes = Files.readAllBytes(path);
如果想将文件当做字符串读入,那么可以在调用readAllBytes 之后,调用下面的代码:
String content = new String(bytes,charset);
如果希望将文件当做行序列读入:
List<String> lines = Files.readAllLines(path,charset);
如果希望写出一个字符串到文件中:
Files.write(path,content,getBytes(charset));
向指定文件追加内容,可以调用:
Files.write(path,content.getBytes(charset),StandardOpenOption.APPEND);
还可以用下面的语句将一个行的集合写出到文件中:
Files.write(path,lines);
这些简便方法用于处理中等长度的文本文件,如果要处理的文件长度比较大,或者是二进制文件,那么还是应该用流或者读入器/写出器:

InputStream in = Files.newInputStream(path);OutputStream out = Files.newOutputStream(path);Reader in = Files.newBufferedReader(path,charset);Writer out = Files.newBufferedWriter(path,charset);

复制、移动和删除文件

将一个文件从一个位置复制到另一个位置可以直接调用:
Files.copy(fromPath,toPath);
移动(即复制并删除原文件)可以调用:
Files.move(fromPath,toPath);
如果目标路径已经存在,那么复制或移动将失败,如果想要覆盖已有的目标路径,可以使用REPLACE_EXISTING选项。如果想要复制所有的文件属性,可以使用COPY_ATTRIBUTES选项。
Files.copy(fromPath,toPath,StandardCopyOption.REPLACE_EXISTING,StandardCopyOption.COPY_ATTRIBUTES);
你可以将移动操作定义为原子性的,这样就可以保证要么移动操作成功完成,要么原文件继续保持在原来的位置。
Files.move(fromPath,toPath,StandardCopyOption.ATOMIC_MOVE);
最后删除文件可以调用:
Files.delete(path);
如果删除的文件不存在,这个方法就会抛出异常。因此可以转而使用下面的方法:
`boolean deleted = Files.deleteIfExists(path);
该删除方法还可以用来移除空目录。

创建文件和目录

创建新目录可以调用:
Files.createDirectory(path);
其中路径中除最后一个部件外,其他部分都必须是已存在的。要创建路径中的中间目录,应该使用:
Files.createDirectories(path);
如果文件已经存在了,那么这个调用就会抛出异常。

迭代目录中的文件

Files类设计了一个方法,它可以产生一个Iterable对象。

try(DirectoryStream<Path> entries = Files.newDirectoryStream(path)) //Java 7新特性,支持try后面跟随()管理释放资源{   for(Path entry:entries)        System.out.println(entry.getFileName());}catch(Exception e){}

可以用glob模式来过滤文件:
try(DirectoryStream<Path> entries = Files.newDirectoryStream(path,"*.java"))

如果想要访问某个目录的所有子孙成员,可以转而调用walkFileTree方法,并向其传递一个FileVisitor 类型的对象,这个对象会得到一系列通知:

  • 在遇到一个文件或目录时:FileVisitResult visitFile(T path,BasicFileAttributes attrs)
  • 在一个目录被处理前:FileVisitResult preVisitDirectory(T dir,IOException ex)
  • 在一个目录被处理前:FileVisitResult postVisitDirectory(T dir,IOException ex)
  • 在试图访问文件或目录发生错误,例如没有权限打开目录:FileVisitResult visitFileFailed(path,IOException ex)

    对于上述每种情况,都可以指定是否希望执行下面的操作:

  • 继续访问下一个文件:FileVisitResult.CONTINUE
  • 继续访问,但是不再访问这个目录下的任何项了:FileVisitResult.SKIP_SUBTREE
  • 继续访问,但是不再访问这个文件的兄弟文件了:FileVisitResult.SKIP_SIBLINGS
  • 终止访问:FileVisitResult.TERMINATE
    当有任何方法抛出异常时,就会终止访问,而这个异常会从walkFileTree 方法中抛出。
Files.walkFileTree(absolute,new SimpleFileVisitor<Path>(){            public FileVisitResult preVisitDirectory(Path path,BasicFileAttributes attrs) throws IOException{                System.out.println(path);                return FileVisitResult.CONTINUE;            }            public FileVisitResult visitFileFailed(Path path,IOException exc) throws IOException{                return FileVisitResult.CONTINUE;            }            public FileVisitResult visitFile(Path path,BasicFileAttributes attrs) throws IOException{                System.out.println(path);                return FileVisitResult.CONTINUE;            }        });

ZIP文件系统

Paths 类会在默认文件系统中查找路径,即在用户本地磁盘中的文件。也可以有别的文件系统,其中最有用的之一是ZIP文件系统。如果zipname 是某个ZIP文件的名字,那么下面的调用
FileSystem fs =FileSystems.newFilseSystem(Paths.get(zipname),null);
将建立一个文件系统,它包含ZIP文档中的所有文件,如果知道文件名,那么从ZIP文档中复制出这个文件就会变得容易:
Files.copy(fs.getPath(sourceName),targetPath);

以上内容和代码来源于Java 核心技术卷Ⅱ (原书第九版)

原创粉丝点击