Java 7 中 NIO.2 的使用——第四节 文件和目录

  Files类提供了很多方法用于检查在于你真正实际去操作一个文件或目录。这些方法强烈推荐,也非常有用,也能避免很多异常的发生。例如,一个很好的习惯就是在你试着移动一个文件从一个地方到另一个地方的时候,先检查文件是否存在。

  检查一个文件或目录是否存在

  在前面的例子中已经演示到,Path实例能够有效的映射到一个文件或是目录甚至这个文件或目录物理上根本不存在。再是,Path的很多方法不会实际操作文件本身就能成功地应用。所以,事先判断一个目录或是文件存在就显得非常重要。下面有两个方法用来判断文件是否存在。

  • exists():检查一个文件是否存在
  • notExists(): 检查一个文件是否不存在

  这两个方法都包含两个参数,第一个参数是path实例,第二个参数符号连接的文件是否处理。exist()方法返回 true如果文件存在。下下面代码:

Path path = FileSystems.getDefault().getPath("C:/rafaelnadal/tournaments/2009","AEGON.txt");…boolean path_exists = Files.exists(path, new LinkOption[]{LinkOption.NOFOLLOW_LINKS});

  注意:!Files.exists(…)Files.notExists(…)方法不是等价的,notExists()不是exists()方法的补充。

  检查文件的可访问性

  一个很好的习惯就是在访问一个文件前先检查它的可访问级别,可以使用isReadable(), isWritable(), isExecutable()这些方法。在传递一个路径被确认后,如果文件可读,可写,可执行,那么虚拟机将有权限去访问这个文件。

  另外,可以使用isRegularFile()方法在判断文件是不是一个正常的文件。正常的文件是指没有特别的特性(例如,不是符号链接,不是目录等),包含真实的数据(例如二进制文件)。上代码。

C:\rafaelnadal\tournaments\2009 directory (the file must exist) looks like the following:Path path = FileSystems.getDefault().getPath("C:/rafaelnadal/tournaments/2009","AEGON.txt");boolean is_readable = Files.isReadable(path);boolean is_writable = Files.isWritable(path);boolean is_executable = Files.isExecutable(path);boolean is_regular = Files.isRegularFile(path, LinkOption.NOFOLLOW_LINKS);if ((is_readable) && (is_writable) && (is_executable) && (is_regular)) {System.out.println("The checked file is accessible!");} else {System.out.println("The checked file is not accessible!");}

  或者像下面这样的代码:

boolean is_accessible = Files.isRegularFile(path) & Files.isReadable(path) &  Files.isExecutable(path) & Files.isWritable(path);if (is_accessible) {System.out.println("The checked file is accessible!");} else {System.out.println("The checked file is not accessible!");}

   检查两个路径是否指向同一相同文件

  在以前的章节中,有可以看到如何去检查一个符号链接和目标文件是否是同一个文件。还有一个常用的测试就是你你可以使用isSameFile()方法去检查不同的Paths的表达是否指向同一个文件。例如,一个相对路径和一个绝对路径可能指向同一个文件。假设有一文件的路径为C:\rafaelnadal\tournaments\2009\MutuaMadridOpen.txt,有下面三种Path的表达方式。

Path path_1 = FileSystems.getDefault().getPath("C:/rafaelnadal/tournaments/2009","MutuaMadridOpen.txt");
Path path_2 = FileSystems.getDefault().getPath("/rafaelnadal/tournaments/2009", "MutuaMadridOpen.txt"); 
Path path_3 = FileSystems.getDefault().getPath("/rafaelnadal/tournaments/dummy/../2009", "MutuaMadridOpen.txt");try {boolean is_same_file_12 = Files.isSameFile(path_1, path_2);boolean is_same_file_13 = Files.isSameFile(path_1, path_3);boolean is_same_file_23 = Files.isSameFile(path_2, path_3);System.out.println("is same file 1&2 ? " + is_same_file_12);System.out.println("is same file 1&3 ? " + is_same_file_13);System.out.println("is same file 2&3 ? " + is_same_file_23);} catch (IOException e) {System.err.println(e);}

  输出结果为:

is same file 1&2 ? true

is same file 1&3 ? true

is same file 2&3 ? true

  检查文件是否可见。

  如果你需要找出一个文件是否可见,可以使用Files.isHidden()方法,需要注意的是,“hidden”这个概念是依赖平台的。

Path path = FileSystems.getDefault().getPath("C:/rafaelnadal/tournaments/2009", "MutuaMadridOpen.txt");…try {boolean is_hidden = Files.isHidden(path);System.out.println("Is hidden ? " + is_hidden);} catch (IOException e) {System.err.println(e);}

  --------------------------------------------------------------------------------------------------------------------------------

  创建和读取目录

  当我们需要创建和读取一个目录时,NIO.2提供了一些类方法在Files类中。在这一节中,你将会发现如何列出文件系统的根,创建目录以及临时目录,列出目录里的内容,还可以对目录进行过滤。

  列出文件系统的根目录

  在Java 6 中,文件系统的根目录被抽取出一个存放File对象的数组中,从Java 7 开始,NIO.2 会把根目录作为Path对象的Iterable,通过getRootDirectories()方法返回这个Iterable接口。

Iterable<Path> dirs = FileSystems.getDefault().getRootDirectories();for (Path name : dirs) {System.out.println(name);} 

  可能的输出结果是:

  C:\

  D:\

  E:\

  创建一个新的目录

  直接上代码。

Path newdir = FileSystems.getDefault().getPath("C:/rafaelnadal/tournaments/2010/");…try {Files.createDirectory(newdir);} catch (IOException e) {System.err.println(e);} 

  当然,也可以在创建目录时设置权限信息:

Path newdir = FileSystems.getDefault().getPath("/home/rafaelnadal/tournaments/2010/");…Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rwxr-x---");FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms);try {Files.createDirectory(newdir, attr);} catch (IOException e) {System.err.println(e);}

  注意,如果要创建的目录存在,则 createDirectory()方法会抛出异常。

  有的时候,我们需要多层的目录,例如\statistics\win\prizes,当然你可以使用createDirectory()方法,其实还可以优雅地使用Files.createDirectories()方法,

Path newdir= FileSystems.getDefault().getPath("C:/rafaelnadal/", "statistics/win/prizes");…try {Files.createDirectories(newdir);} catch (IOException e) {System.err.println(e);}

  列出目录里的内容

Path path = Paths.get("C:/rafaelnadal/tournaments/2009");//no filter appliedSystem.out.println("\nNo filter applied:");try (DirectoryStream<Path> ds = Files.newDirectoryStream(path)) {for (Path file : ds) {System.out.println(file.getFileName());}}catch(IOException e) {System.err.println(e);}

  使用正则表达式列出目录里的内容

Path path = Paths.get("C:/rafaelnadal/tournaments/2009");…//glob pattern appliedSystem.out.println("\nGlob pattern applied:");try (DirectoryStream<Path> ds = Files.newDirectoryStream(path, "*.{png,jpg,bmp}")) {for (Path file : ds) {System.out.println(file.getFileName());}} catch (IOException e) {System.err.println(e);}

  用户自定义过滤器列出目录里的内容

  如果正则表达式不能满足你的需求,你也可以自定义自己的过滤器,这个任务很简单,只需要继承DirectoryStream.Filter<T>接口即可。此接口有accept()方法,一个Path是接受还是拒绝完全基于你的实现。下面的例子,只列出给定目录下的所有目录。

Path path = Paths.get("C:/rafaelnadal/tournaments/2009");…//user-defined filter - only directories are acceptedDirectoryStream.Filter<Path> dir_filter = new DirectoryStream.Filter<Path>() {public boolean accept(Path path) throws IOException {return (Files.isDirectory(path, NOFOLLOW_LINKS));}}; 
System.out.println("\nUser defined filter applied:");try (DirectoryStream<Path> ds = Files.newDirectoryStream(path, dir_filter)) {for (Path file : ds) {System.out.println(file.getFileName());}} catch (IOException e) {System.err.println(e);}

  还有如下自定义的过滤器。

    1.列出文件或目录大小超过200kb的列表。

public boolean accept(Path path) throws IOException {return (Files.size(path) > 204800L);}};

    2.列出只有今天修改的文件的列表。

DirectoryStream.Filter<Path> time_filter = new DirectoryStream.Filter<Path>() {public boolean accept(Path path) throws IOException {long currentTime = FileTime.fromMillis(System.currentTimeMillis()).to(TimeUnit.DAYS);long modifiedTime = ((FileTime) Files.getAttribute(path, "basic:lastModifiedTime", NOFOLLOW_LINKS)).to(TimeUnit.DAYS);if (currentTime == modifiedTime) {return true;}return false;}};

    3.只列出隐藏的文件或目录

DirectoryStream.Filter<Path> hidden_filter = new DirectoryStream.Filter<Path>() {public boolean accept(Path path) throws IOException {return (Files.isHidden(path));}};

  -----------------------------------------------------------------------------------------------------------------------------

   创建,读取和写文件

  一个Stream表示输入源或是输出目的地。stream支持不同种类的数据,例如字符串,字节,基本数据类型,本地化字符还有对象。在一个无缓冲的流,每个读或写请求由底层操作系统直接处理,而在有缓存的流中,数据从内存中称之为缓冲区的地方读取,只有当缓冲区为空的时候本地输入API会被调用。类似的,缓存的输出流把数据写入到缓冲区中,只有缓冲区写满以后本地输出API才会被调用。当缓冲区输出完没有等待填满时,外我们说这个缓冲区是清空的。

  使用标准的打开选项

  从NIO.2 开始,文件的创建,读取和写入操作都支持一个可选参数——OpenOption,它用来配置外面如何打开或是创建一个文件。实际上OpenOption是java.nio.file包中一个接口,它有两个实现类:LinkOptionStandardOpenOption。下面就是选项枚举。

READ以读取方式打开文件
WRITE  已写入方式打开文件
CREATE如果文件不存在,创建
CREATE_NEW如果文件不存在,创建;若存在,异常。
APPEND在文件的尾部追加
DELETE_ON_CLOSE当流关闭的时候删除文件
TRUNCATE_EXISTING把文件设置为0字节
SPARSE文件不够时创建新的文件
SYNC同步文件的内容和元数据信息随着底层存储设备
DSYNC同步文件的内容随着底层存储设备

 

 

 

 

 

 

 

 

 

 

   创建一个文件

  创建文件和创建目录类似,可以使用Files.createFile()方法,也可以在创建的时候添加权限信息。

Path newfile = FileSystems.getDefault().getPath("C:/rafaelnadal/tournaments/2010/SonyEricssonOpen.txt");…try {Files.createFile(newfile);} catch (IOException e) {System.err.println(e);}

  创建带有权限的文件.

Path newfile = FileSystems.getDefault().getPath("/home/rafaelnadal/tournaments/2010/SonyEricssonOpen.txt");Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rw-------");FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms);try {Files.createFile(newfile, attr);} catch (IOException e) {System.err.println(e);}

  写入一个小文件

  NIO.2提供了非常优雅的方式去写入小的二进制或是文本文件。使用Files.write()方法来创建。

  使用write()方法写入bytes

Path ball_path = Paths.get("C:/rafaelnadal/photos", "ball.png");…byte[] ball_bytes = new byte[]{(byte)0x89,(byte)0x50,(byte)0x4e,(byte)0x47,(byte)0x0d,(byte)0x0a,(byte)0x1a,(byte)0x0a,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x0d,(byte)0x49,(byte)0x48,(byte)0x44,(byte)0x52,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x10,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x10,(byte)0x08,(byte)0x02,(byte)0x00,            …(byte)0x49,(byte)0x45,(byte)0x4e,(byte)0x44,(byte)0xae,(byte)0x42,(byte)0x60,(byte)0x82 
};try {Files.write(ball_path, ball_bytes);} catch (IOException e) {System.err.println(e);}

  按行写入文件

Path rf_wiki_path = Paths.get("C:/rafaelnadal/wiki", "wiki.txt");…Charset charset = Charset.forName("UTF-8");ArrayList<String> lines = new ArrayList<>();lines.add("\n");lines.add("Rome Masters - 5 titles in 6 years");lines.add("Monte Carlo Masters - 7 consecutive titles (2005-2011)");lines.add("Australian Open - Winner 2009");lines.add("Roland Garros - Winner 2005-2008, 2010, 2011");lines.add("Wimbledon - Winner 2008, 2010");lines.add("US Open - Winner 2010");try {Files.write(rf_wiki_path, lines, charset, StandardOpenOption.APPEND);} catch (IOException e) {System.err.println(e);} 

   读取一个小文件

  NIO.2 提供了两个方法Files.readAllBytes() 和 Files.readAllLines()方法用来读取小的字节或是文本文件。很简单,直接看代码。

Path ball_path = Paths.get("C:/rafaelnadal/photos", "ball.png");…try {byte[] ballArray = Files.readAllBytes(ball_path);            } catch (IOException e) {System.out.println(e);}
Path wiki_path = Paths.get("C:/rafaelnadal/wiki", "wiki.txt");…Charset charset = Charset.forName("ISO-8859-1");try {List<String> lines = Files.readAllLines(wiki_path, charset);for (String line : lines) {System.out.println(line);}} catch (IOException e) {System.out.println(e);}

  根据官方文档,该方法识别以下行认为是结束符:

  • \u000D followed by \u000A: 回车接着换行
  • \u000A: 换行
  • \u000D:回车

  使用缓存流进行工作

  在多数操作系统中,系统调用文件的读写是一件非常昂贵的操作。在缓冲的方法区和操作系统之间提供了一块内存区域很好的解决了这个问题。

在调用本地API之前,这些方法在操作系统和应用程序之间的缓存中获取或设置数据。这样大大地提高了效率因为它减少了调用系统的次数。只有在缓冲区为空或是满的时候,才会访问硬盘,根据读取或写入操作。NIO.2提供了两个通过缓存读取和写入文件的方法:Files.newBufferedReader()Files.newBufferedWriter(),相应的,这两个方法会得到Path实例并返回BufferedReaderBufferedWriter 实例。

  使用 newBufferedWriter()方法

   不多说,上代码。

Path wiki_path = Paths.get("C:/rafaelnadal/wiki", "wiki.txt");…Charset charset = Charset.forName("UTF-8");String text = "\nVamos Rafa!";try (BufferedWriter writer = Files.newBufferedWriter(wiki_path, charset, StandardOpenOption.APPEND)) {writer.write(text);} catch (IOException e) {System.err.println(e);}

  使用newBufferedReader()方法

Path wiki_path = Paths.get("C:/rafaelnadal/wiki", "wiki.txt");…Charset charset = Charset.forName("UTF-8");try (BufferedReader reader = Files.newBufferedReader(wiki_path, charset)) {String line = null;while ((line = reader.readLine()) != null) {System.out.println(line);}} catch (IOException e) {System.err.println(e);} 

   使用无缓存的流工作

  可以使用NIO.2直接获取无缓存的流也可以使用java.io的API中的包装类转换成缓存流。使用无缓存的流的方法有Files.newInputStream()(从一个文件中读取到输入流中),Files.newOutputStream()方法(从输出流中写入到文件中)。

  使用newOutputStream() 方法

  这个方法获取指向文件的路径和说明文件时如何打开的,它会返回一个线程安全的无缓存的刘对象,用来写入字节到文件中。

  上菜。

//C:\rafaelnadal\equipment\racquet.txt (the file doesn’t initially exist, but it will be automatically created because no options are specified):Path rn_racquet = Paths.get("C:/rafaelnadal/equipment", "racquet.txt");String racquet = "Racquet: Babolat AeroPro Drive GT";byte data[] = racquet.getBytes();try (OutputStream outputStream = Files.newOutputStream(rn_racquet)) {outputStream.write(data);} catch (IOException e) {System.err.println(e);}

  此外,如果你有更好的主意使用缓存的流代替上面的代码,推荐使用基于java.io的API的转换,正如下面的代码,

Path rn_racquet = Paths.get("C:/rafaelnadal/equipment", "racquet.txt");String string = "\nString: Babolat RPM Blast 16";try (OutputStream outputStream = Files.newOutputStream(rn_racquet, StandardOpenOption.APPEND);BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream))) {writer.write(string);} catch (IOException e) {System.err.println(e);}

  使用 newInputStream()方法

//The following code snippet reads the content of the file racquet.txt (the file must exist):
 
Path rn_racquet = Paths.get("C:/rafaelnadal/equipment", "racquet.txt");…int n;     
try (InputStream in = Files.newInputStream(rn_racquet)) {while ((n = in.read()) != -1) {System.out.print((char)n);                }} catch (IOException e) {System.err.println(e);}

  从此而外,你也可以把一个无缓存的流转换成缓存流,下面的代码跟上面的代码实现了相同的功能,但是它更加高效。

Path rn_racquet = Paths.get("C:/rafaelnadal/equipment", "racquet.txt");…try (InputStream in = Files.newInputStream(rn_racquet);BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {String line = null;while ((line = reader.readLine()) != null) {System.out.println(line);}} catch (IOException e) {System.err.println(e);}

  ------------------------------------------------------------------------------------------------------------------------

   创建临时目录和文件

  一个临时目录用来存放临时文件。临时目录的存放位置依赖于操作系统。在Windows下,临时目录可以通过“TEMP”环境变量来设置,通常的位置是:C:\Temp, %Windows%\Temp,或者在每个用户的:Local Settings\Temp。而Unix/Linux的临时目录为:/tmp/var/tmp。

  创建一个临时目录

  在NIO.2中通过createTempDirectory()方法用来创建一个临时目录,创建默认的操作系统的临时目录可以调用createTempDirectory()两个参数的方法:前一个用来设置目录的名字的前缀(可以为null),后一个可选参数用来设置文件属性。

String tmp_dir_prefix = "nio_";try {//passing null prefixPath tmp_1 = Files.createTempDirectory(null);System.out.println("TMP: " + tmp_1.toString());//set a prefixPath tmp_2 = Files.createTempDirectory(tmp_dir_prefix);System.out.println("TMP: " + tmp_2.toString());} catch (IOException e) {System.err.println(e);} 

  则输出结果为:

TMP: C:\Users\Leo\AppData\Local\Temp\3238630399269555448

TMP: C:\Users\Leo\AppData\Local\Temp\nio_1097550355199661257

  如果你不知道系统的默认临时目录的路径,也可以使用下面的代码:

//output: C:\Users\Leo\AppData\Local\Temp\String default_tmp = System.getProperty("java.io.tmpdir");System.out.println(default_tmp); 

  更进一步,你也可以通过createTempDirectory()方法自定义临时目录的路径,

Path basedir = FileSystems.getDefault().getPath("C:/rafaelnadal/tmp/");String tmp_dir_prefix = "rafa_";try {if (Files.notExists(basedir)) {Path dir = Files.createDirectories(basedir);// create a tmp directory in the base dirPath tmp = Files.createTempDirectory(dir, tmp_dir_prefix);System.out.println("TMP: " + tmp.toString());}} catch (IOException e) {System.err.println(e);}

  输出结果为:

TMP: C:\rafaelnadal\tmp\rafa_1753327229539718259

  使用Shutdown-Hook删除临时文件

  大部分操作系统都会自动地删除临时目录(如果不能,你可以使用多种清理软件),但是,有时候你需要程序级别的控制文件的删除过程。createTempDirectory()方法只是完成了一半的工作,因为删除工作由你负责。为了这一原因你可以shutdown-hook机制,这个机制用来执行任何资源的清理或者保持在JVM关闭之前生效。这个钩子可以是Java线程的实现。Thread的run()方法可以在JVM关闭时执行操作。

    Figure 4-1. The simple flow design of a shutdown-hook

Runtime.getRuntime().addShutdownHook(new Thread() {@Overridepublic void run() {System.out.println("Shutdown-hook activated ...");//… here, cleanup/save resources 
System.out.println("Shutdown-hook successfully executed ...");}}); 

  shutdown-hook机制是一个很好的方法用来解决JVM关闭时删除临时目录的问题。同时你也知道,如果目录不为空的话是无法删除的。所以你需要循环每一层目录删除每一个文件直至每个目录为空再删除目录本身。

  使用deleteOnExit() 方法删除临时目录

  另一种删除临时目录的解决方法是调用deleteOnExit()方法,这个方法在java.io.Fi类中。它将在JVM关闭时删除传递的文件或目录参数。因为这个方法需要被每个目录和文件调用,所以它最不吸引人的地方就是需要为每个临时实体消耗内存。

  注意,如果你的系统需要长时间运行或者在很短的时间内需要创建很多文件和目录,则使用deleteOnExit()是个很坏的主意。它需要占用大量内存即使JVM退出后还没有释放。

  下面演示deleteOnExit()方法的使用。

Path basedir = FileSystems.getDefault().getPath("C:/rafaelnadal/tmp/");String tmp_dir_prefix = "rafa_";try {//create a tmp directory in the base dirPath tmp_dir = Files.createTempDirectory(basedir, tmp_dir_prefix);File asFile = tmp_dir.toFile();asFile.deleteOnExit();//simulate some I/O operations over the temporary file by sleeping 10 seconds//when the time expires, the temporary file is deleted            //EACH CREATED TEMPORARY ENTRY SHOULD BE REGISTERED FOR DELETE ON EXITThread.sleep(10000);//operations done
} catch (IOException | InterruptedException e) {System.err.println(e);} 

  创建临时文件

  不罗嗦,一些概念跟创建临时目录一样,直接上代码。

String tmp_file_prefix = "rafa_";String tmp_file_sufix=".txt";try {//passing null prefix/suffixPath tmp_1 = Files.createTempFile(null,null);System.out.println("TMP: " + tmp_1.toString());//set a prefix and a suffixPath tmp_2 = Files.createTempFile(tmp_file_prefix, tmp_file_sufix);System.out.println("TMP: " + tmp_2.toString());} catch (IOException e) {System.err.println(e);} 

  同样,你也可以自定义临时文件的目录。

Path basedir = FileSystems.getDefault().getPath("C:/rafaelnadal/tmp");String tmp_file_prefix = "rafa_";String tmp_file_sufix=".txt";try {Path tmp_3 = Files.createTempFile(basedir, tmp_file_prefix, tmp_file_sufix);System.out.println("TMP: " + tmp_3.toString());} catch (IOException e) {System.err.println(e);} 

  使用 Shutdown-Hook机制删除临时文件

  下面代码在C:\rafaelnadal\tmp下创建临时文件,等待10秒钟后,当JVM退出后删除临时文件。

Path basedir = FileSystems.getDefault().getPath("C:/rafaelnadal/tmp");String tmp_file_prefix = "rafa_";String tmp_file_sufix = ".txt";try {final Path tmp_file = Files.createTempFile(basedir, tmp_file_prefix, tmp_file_sufix);Runtime.getRuntime().addShutdownHook(new Thread() {@Overridepublic void run() {System.out.println("Deleting the temporary file ...");try {Files.delete(tmp_file);} catch (IOException e) {System.err.println(e);}System.out.println("Shutdown hook completed...");}});//simulate some I/O operations over the temporary file by sleeping 10 seconds//when the time expires, the temporary file is deleted            Thread.sleep(10000);//operations done
} catch (IOException | InterruptedException e) {System.err.println(e);} 

  使用 deleteOnExit() 方法删除临时文件

Path basedir = FileSystems.getDefault().getPath("C:/rafaelnadal/tmp");String tmp_file_prefix = "rafa_";String tmp_file_sufix = ".txt";try {final Path tmp_file = Files.createTempFile(basedir, tmp_file_prefix, tmp_file_sufix);File asFile = tmp_file.toFile();asFile.deleteOnExit();//simulate some I/O operations over the temporary file by sleeping 10 seconds//when the time expires, the temporary file is deletedThread.sleep(10000);//operations done
} catch (IOException | InterruptedException e) {System.err.println(e);} 

  使用DELETE_ON_CLOSE枚举参数删除临时文件

  另一种比较独特的删除临时文件的方式是使用DELETE_ON_CLOSE选项。它会在流关闭的时候删除文件。

Path basedir = FileSystems.getDefault().getPath("C:/rafaelnadal/tmp");String tmp_file_prefix = "rafa_";String tmp_file_sufix = ".txt";Path tmp_file = null;try {tmp_file = Files.createTempFile(basedir, tmp_file_prefix, tmp_file_sufix);} catch (IOException e) {System.err.println(e);}try (OutputStream outputStream = Files.newOutputStream(tmp_file, StandardOpenOption.DELETE_ON_CLOSE);BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream))) {//simulate some I/O operations over the temporary file by sleeping 10 seconds//when the time expires, the temporary file is deleted            Thread.sleep(10000);//operations done} catch (IOException | InterruptedException e) {System.err.println(e);} 

  除此而外,你甚至不用调用createTempFile()方法,当你使用CREATE选项与DELETE_ON_CLOSE组合使用时:

String tmp_file_prefix = "rafa_";String tmp_file_sufix = ".txt";Path tmp_file = null;tmp_file = FileSystems.getDefault().getPath("C:/rafaelnadal/tmp", tmp_file_prefix + "temporary" + tmp_file_sufix);try (OutputStream outputStream = Files.newOutputStream(tmp_file, StandardOpenOption.CREATE, StandardOpenOption.DELETE_ON_CLOSE);BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream))) {//simulate some I/O operations over the temporary file by sleeping 10 seconds//when the time expires, the temporary file is deleted            Thread.sleep(10000);//operations done} catch (IOException | InterruptedException e) {System.err.println(e);} 

  目录或文件的删除,复制和移动

  删除目录或文件

  NIO.2提供了两个用来删除目录或文件的方法:Files.delete()Files.deleteIfExits()。这两个都接受单一的参数指定删除的路径。但是Files.delete()无返回值,Files.deleteIfExits()返回boolean值根据文件是否删除成功。Files.delete()试图删除路径下的文件或目录,如果删除失败,则会抛出以下异常。NoSuchFileException (i路径不存在), DirectoryNotEmptyException (i目录不为空), IOException (输入输出错误发生), or SecurityException (无删除权限)。

Path path = FileSystems.getDefault().getPath("C:/rafaelnadal/photos", "rafa_1.jpg");//delete the filetry {Files.delete(path);} catch (NoSuchFileException | DirectoryNotEmptyException | IOException | SecurityException e) {System.err.println(e);} 

  就像名字建议的一样,Files.deleteIfExists()方法只有在文件存在的时候删除,这就意味着如果文件不存在(代替了抛出NoSuchFileException异常)不能删除的情况下返回boolean值false。这种应用在多线程删除文件的时候非常有用。你不想第一个线程就抛出异常。

try {boolean success = Files.deleteIfExists(path);System.out.println("Delete status: " + success);} catch (DirectoryNotEmptyException | IOException | SecurityException e) {System.err.println(e);} 

  复制目录或文件

  NIO.2中提供了Files.copy()方法来复制目录和文件。它提供了StandardCopyOptionLinkOption 枚举下的很多选项作为参数:

  • REPLACE_EXISTING: 如果目标文件存在,则替换;当拷贝符号链接文件时,真实文件不拷贝,值拷贝符号链接文件。
  • COPY_ATTRIBUTES: 拷贝文件并关联的属性。
  • NOFOLLOW_LINKS: 不包含符号链接的文件或目录.

  这些枚举类型静态导入到程序中,

 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES;import static java.nio.file.LinkOption.NOFOLLOW_LINKS; 

  在两个路径间复制

Path copy_from = Paths.get("C:/rafaelnadal/grandslam/AustralianOpen", "draw_template.txt");Path copy_to= Paths.get("C:/rafaelnadal/grandslam/USOpen",copy_from.getFileName().toString());try {Files.copy(copy_from, copy_to, REPLACE_EXISTING, COPY_ATTRIBUTES, NOFOLLOW_LINKS);} catch (IOException e) {System.err.println(e);} 

   从一个输入流中拷贝到文件

Path copy_from = Paths.get("C:/rafaelnadal/grandslam/AustralianOpen", "draw_template.txt");Path copy_to = Paths.get("C:/rafaelnadal/grandslam/Wimbledon", "draw_template.txt");try (InputStream is = new FileInputStream(copy_from.toFile())) {Files.copy(is, copy_to, REPLACE_EXISTING);} catch (IOException e) {System.err.println(e);}

  文件输入流可能来自不同的方式。例如下面的代码中文件来自于互联网的URL。

Path copy_to = Paths.get("C:/rafaelnadal/photos/rafa_winner_2.jpg");URI u = URI.create("https://lh6.googleusercontent.com/--udGIidomAM/Tl8KTbYd34I/AAAAAAAAAZw/j2nH24PaZyM/s800/rafa_winner.jpg");try (InputStream in = u.toURL().openStream()) {Files.copy(in, copy_to);} catch (IOException e) {System.err.println(e);}

  从一个文件拷贝到输出流

Path copy_from = Paths.get("C:/rafaelnadal/grandslam/AustralianOpen", "draw_template.txt");Path copy_to = Paths.get("C:/rafaelnadal/grandslam/RolandGarros", "draw_template.txt");try (OutputStream os = new FileOutputStream(copy_to.toFile())) {Files.copy(copy_from, os);} catch (IOException e) {System.err.println(e);} 

  移动文件和目录

  在这部分,你将会学习到 如何使用Files.move()方法移动目录和文件。这个方法有一可选参数用来指定一枚举类型:

  • REPLACE_EXISTING:若目标文件存在,则替换.
  • ATOMIC_MOVE: 执行的文件将被作为一个原子操作,保证任何过程监控文件的目录将会访问一个完整的文件。

  默认情况下(没有明确指定选项) move()尝试移动文件到目标文件,如果目标文件存在,则会失败。除非源文件与目标文件是同一文件(isSameFile()返回 true),这种情况方法不会生效。

Path movefrom = FileSystems.getDefault().getPath("C:/rafaelnadal/rafa_2.jpg");Path moveto = FileSystems.getDefault().getPath("C:/rafaelnadal/photos/rafa_2.jpg");try {Files.move(movefrom, moveto, StandardCopyOption.REPLACE_EXISTING);} catch (IOException e) {System.err.println(e);}

  如果你不想hard-code移动文件的名字,可以使用Path.resolve()方法,通过这种方法,你可以直接从需要移动的路径中抽取文件名字给移动文件的名字。

   Path movefrom = FileSystems.getDefault().getPath("C:/rafaelnadal/rafa_2.jpg");Path moveto_dir = FileSystems.getDefault().getPath("C:/rafaelnadal/photos");System.out.println(moveto_dir.resolve(movefrom.getFileName())); // C:\rafaelnadal\photos\rafa_2.jpgtry {Files.move(movefrom, moveto_dir.resolve(movefrom.getFileName()), StandardCopyOption.REPLACE_EXISTING);} catch (IOException e) {System.err.println(e);}

  重命名文件

  这开起来有些诡异,可以通过Files.move()Path.resolveSibling() 重命名一个文件。

Path movefrom = FileSystems.getDefault().getPath("C:/rafaelnadal/photos/rafa_2.jpg");try {Files.move(movefrom, movefrom.resolveSibling("rafa_2_renamed.jpg"), StandardCopyOption.REPLACE_EXISTING);} catch (IOException e) {System.err.println(e);}

  完。

 

 

 

 

  

  

转载于:https://www.cnblogs.com/IcanFixIt/p/4838375.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/458815.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机二级access知识点6,2019年计算机二级ACCESS考试知识点:关系数据模型

【导语】2019年计算机二级考试备考正在进行中&#xff0c;为了方便考生及时有效的备考&#xff0c;那么&#xff0c;无忧考网为您精心整理了2019年计算机二级ACCESS考试知识点&#xff1a;关系数据模型&#xff0c;欢迎大家的关注。如想获取更多计算机二级考试的备考资料&#…

Moldflow中文版注塑流动分析案例导航视频教程

http://item.taobao.com/item.htm?spma1z10.5.w4002-9510581626.18.30lDTO&id43054534418 QQ&#xff1a;2911984429 http://aidem.lingw.net/

湖北大学计算机袁云,暑期走访不停歇 远赴异地送关怀——学校慰问离退休教职工和校友...

不畏酷暑送清风&#xff0c;心常为老怀关爱。7月至8月&#xff0c;正值高温时节&#xff0c;校领导和各单位负责人根据学校党委的安排&#xff0c;赴深圳、广州、北京、上海等地走访慰问70岁以上离退休教职工和部分校友&#xff0c;把学校的问候和祝福送到他们身边。“对老同志…

MATLAB各类函数详细讲解 simulike系统仿真分析

http://item.taobao.com/item.htm?spma230r.1.14.40.yWjJFw&id43113292964&ns1&abbucket2&_uk10ekfuf6120#detail Matlab基本操作函数 SIMULINK仿真函数 插值与拟合函数视频教程 符号运算函数视频教程 概率统计函数视频教程 级数与微积分函数视频教程 矩阵运…

Github Coding Developer Book For LiuGuiLinAndroid

Github Coding Developer Book For LiuGuiLinAndroid 收集了这么多开源的PDF&#xff0c;也许会帮到一些人&#xff0c;现在里面的书籍还不是很多&#xff0c;我也在一点点的上传&#xff0c;才上传不到一半&#xff0c;没办法&#xff0c;库存太多了 觉得全部pull麻烦的话&…

Linux设备驱动程序(第三版)/深入理解计算机系统(原书第2版)/[Android系统原理及开发要点详解].(韩超,梁泉)百度云盘下载

文档下载云盘连接&#xff1a;http://pan.baidu.com/s/1dDD2sgT 更多其他资料&#xff0c;请关注淘宝&#xff1a;http://shop115376623.taobao.com/ http://item.taobao.com/item.htm?spma230r.1.14.3.ArS64K&id43025290175&ns1&abbucket2&_uk10ekfuf6187#d…

Xcode 5.1 编译模拟器以及真机都能使用的静态库

Xcode 5.1.dmg 下载地址 http://pan.baidu.com/s/1jGJpKm6 1.新建 Framework & Library 工程 我起名叫ShowInfo,下面为其源码 showInfo.h #import <Foundation/Foundation.h> interface ShowInfo : NSObject (void)showInfo; end showInfo.m #import "ShowI…

UVALive 6511 Term Project

Term Project Time Limit: 3000msMemory Limit: 131072KBThis problem will be judged on UVALive. Original ID: 651164-bit integer IO format: %lld Java class name: Main解题&#xff1a;强连通分量 1 #include <bits/stdc.h>2 using namespace std;3 const in…

MATLAB混合编程视频教程下载 SIMULINK系统仿真视频

下载链接&#xff1a; http://item.taobao.com/item.htm?id43401674106 精通MATLAB混合编程视频讲解 MATLAB各类函数视频讲解 基于MATLAB的高等数学问题求解 MATLAB函数速查视频讲解 面向对象C视频教程 五朵金花&#xff0c;带你轻松搞定MATLAB 金花详情&#xff1a; 精通MA…

css z-index

为什么80%的码农都做不了架构师&#xff1f;>>> css z-index 最近在发现z-index在position"relative"的元素中会失效 去掉position属性就正常&#xff1a;z-index1 出现在 z-index999之上 记录一下供以后查看 转载于:https://my.oschina.net/livend/blog…

用c++写的一个词典工具

使用的QT图形界面&#xff0c;用libcurl获取的网页&#xff0c;在之中遇见了很多问题&#xff0c;一直想用c类封装一下libcurl,发现c很不到家啊。索性用了友元函数。 先贴上代码吧 main.cpp #include <stdio.h> #include <stdlib.h> #include <unistd.h>#in…

html5证书,1+X证书Web前端开发HTML专项练习

1 . HTML5 之前的 HTML 版本是&#xff1f; A.HTML 4.01 B.HTML 4 C.HTML 4.1 D.HTML 4.9 2 . HTML5 的正确 doctype 是&#xff1f; A.B.C.3 . 在 HTML5 中&#xff0c;哪个元素用于组合标题元素&#xff1f;A.B.C.D.4 . HTML5 中不再支持下面哪个元素&#xff1f;A.B.C.D.5 .…

PHP中封装mysql数据库链接(简单版)

为什么80%的码农都做不了架构师&#xff1f;>>> 1&#xff0c;封装mysql数据链接需要哪些属性 主机地址&#xff0c;数据库名&#xff0c;数据库密码&#xff0c;数据库名&#xff0c;字符集 2&#xff0c;利用构造方法在实例化类时&#xff0c;php底层会自动执行的…

家用台式计算机的额定功率,台式机的功率(台式电脑电源功率多大才合适?)...

台式机的功率(台式电脑电源功率多大才合适&#xff1f;)组装一台电脑&#xff0c;我们需要先挑选好硬件&#xff0c;搭配硬件最关键点就是CPU和主板兼容性&#xff0c;硬件之间的均衡性、电源功率等&#xff0c;均需要考虑周到。那么台式电脑电源功率多大才合适&#xff1f;下面…

怎么用计算机画正弦函数图像,几何画板如何绘制正弦函数图象

考虑到三角函数问题描点的实际困难&#xff0c;教材表述时借助正弦线利用几何法利用三角函数线作正弦函数图象&#xff0c;但由此带来的困难是如何实现这种效果。如果能让三角函数线动起来&#xff0c;那将会更加直观易懂。几何画板作为使用专业的几何绘图软件&#xff0c;自带…

C#将dll打包到程序中

直接进入主题 先来看一个栗子,假设现在有一个第三方dll namespace TestLibrary1 {public class Test{public void Point(){Console.WriteLine("aaabbbccc");}} } TestLibrary1.dll在项目中引用,然后调用其中的方法Test,将输出aaabbbccc using System;namespace Conso…

Exchange 2016集成ADRMS系列-12:域内outlook 2010客户端测试

接下来&#xff0c;我们来到域内安装了office 2010的机器上进行测试。 首先我们在客户端上强制刷新组策略&#xff0c;把我们刚才设置的策略刷新下来。 然后我们可以运行gpresult /h result.html来看看策略是不是已经下来了。 策略下来之后&#xff0c;我们打开客户端上面的out…

如何用css和HTML结合画熊,结合伪元素实现的纯CSS3高级图形绘制

自小编上次整理了一些基础图形的绘制方法之后&#xff0c;大家都纷纷表示对css3的绘图技巧学习很有帮助。虽说万变不离其宗&#xff0c;再复杂的图形也可以用最简单的三角形或者圆弧组合出来&#xff0c;但仍有不少朋友反映&#xff0c;学会基本图形也不懂得怎样组合&#xff0…

新手学Struts(一)----JSP+Servlet讲解MVC实现原理

MVC基本原理一个简单的例子改良的例子Struts基本流程的实现最近在学SSH&#xff08;Struts HibernateSpring)&#xff0c;这也算是一个比较经典的框架了&#xff0c;之前都是看人家大牛说这个框架&#xff0c;那个框架&#xff0c;说的真溜&#xff0c;自己也是佩服的五体投地啊…

windows下apache+php+mysql 环境配置方法

转自&#xff1a;http://www.jb51.net/article/30128.htm 一 准备 1 下载apache http://httpd.apache.org/download.cgi#apache24 httpd-2.2.22-win32-x86-openssl-0.9.8t.msiopenssl表示带有openssl模块&#xff0c;利用openssl可给Apache配置SSL安全链接 2 下载php http://wi…