在 Java 7 中,java.nio.file.Files 类提供了一系列用于操作文件和目录的静态方法。以下是对Files类的介绍:
读取文件的所有字节并返回一个字节数组。例如:
Path path = Paths.get("D:\\tmp\\root\\test.txt"); byte[] bytes = Files.readAllBytes(path); String content = new String(bytes, StandardCharsets.UTF_8); System.out.println(content);
读取文件的所有行并返回一个字符串列表。例如:
Path path = Paths.get("D:\\tmp\\root\\test.txt"); List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8); for(String line : lines) { System.out.println(line); } Files.write(Path path, byte[] bytes, OpenOption... options)
将字节数组写入文件。可以指定打开文件的选项 OpenOption,你可以使用 StandardOpenOption 枚举对象来指定选项,因为它实现了 OpenOption:
public enum StandardOpenOption extends Enum<StandardOpenOption> implements OpenOption { //... }
StandardOpenOption 取值如下:
StandardOpenOption.APPEND 如果文件是为 WRITE 访问打开的,那么字节将被写入文件的末尾而不是开头。
StandardOpenOption.CREATE 如果文件不存在,则创建新文件。
StandardOpenOption.CREATE_NEW 创建一个新文件,如果文件已经存在则失败。
StandardOpenOption.DELETE_ON_CLOSE 关闭时删除。
StandardOpenOption.DSYNC 要求将文件内容的每次更新同步写入底层存储设备。
StandardOpenOption.READ 为读取访问打开。
StandardOpenOption.SPARSE 稀疏文件。
StandardOpenOption.SYNC 要求文件内容或元数据的每次更新都同步写入底层存储设备。
StandardOpenOption.TRUNCATE_EXISTING 如果文件已经存在,且打开时是以 WRITE 方式访问,则其长度会被截断为 0。
StandardOpenOption.WRITE 为写访问打开。
例如:
Path path = Paths.get("D:\\tmp\\root\\write.txt"); byte[] bytes = "Hello, World!".getBytes(StandardCharsets.UTF_8); Files.write(path, bytes, StandardOpenOption.CREATE, StandardOpenOption.WRITE); String content = new String(Files.readAllBytes(path), StandardCharsets.UTF_8); System.out.println(content); Files.write(Path path, Iterable<? extends CharSequence> lines, Charset charset, OpenOption... options)
将字符串列表写入文件,指定字符编码和打开文件的选项。例如:
Files.write(Paths.get("/path/to/file.txt"), Arrays.asList("Line 1", "Line 2"), StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
当你处理一般大小的文本文件时,通常最简单的办法是将文件内容作为一个字符串或者字符串列表进行处理。如果你的文件很大,或者是二进制文件,你仍然可以使用熟悉的 stream 类或者 reader/writer 类:
Inputstream in = Files.newInputStream(path); OutputStream out = Files.newoutputstream(path); Reader reader = Files.newBufferedReader(path); Writer writer = Files.newBufferedWriter(path);
这些方便的方法可以帮你省去处理 FileInputStream、FileoutputStream、BufferedReader 或者 BufferedWriter 时的工作。
偶尔,你可能希望将一个 InputStream (例如,从一个URL获得) 中的内容保存到一个文件中,那么可以使用:
Files.copy(in,path);
相反,
Files.copy(path,out);
可以将某个文件的内容复制到一个 OutputStream 中。
检查指定路径是否存在。例如:
boolean exists = Files.exists(Paths.get("/path/to/file.txt"));
创建一个新的空文件。如果文件已经存在,则抛出 FileAlreadyExistsException 异常。例如:
Files.createFile(Paths.get("/path/to/newFile.txt"));
创建一个新的目录。如果目录已经存在,则抛出 FileAlreadyExistsException 异常。例如:
Files.createDirectory(Paths.get("/path/to/newDirectory"));
注意:路径中除了最后一部分以外的其他目录,必须都已经存在。
将源文件复制到目标路径。如果目标文件已经存在,则根据具体情况可能会覆盖或抛出异常。例如:
Files.copy(Paths.get("/path/to/sourceFile.txt"), Paths.get("/path/to/targetFile.txt"));
将文件从源路径移动到目标路径。可以用于重命名文件或移动文件到不同的目录。例如:
Files.move(Paths.get("/path/to/sourceFile.txt"), Paths.get("/path/to/newLocation/file.txt"));
删除指定的文件或目录。如果路径指向一个目录,则该目录必须为空才能被删除。例如:
Files.delete(Paths.get("/path/to/file.txt"));
创建一个临时文件。可以指定临时文件所在的目录、文件名前缀、文件名后缀以及文件属性。如果不指定目录,则在默认的临时文件目录中创建文件。文件名前缀和后缀可以用于帮助识别临时文件的用途。例如,前缀可以是"temp_",后缀可以是".txt",这样创建的临时文件可能命名为 "temp_12345.txt"。
try { Path tempFile = Files.createTempFile(null, "temp_", ".txt"); System.out.println("临时文件路径:" + tempFile); // 对临时文件进行操作 //... } catch (IOException e) { e.printStackTrace(); }
创建一个临时目录。可以指定临时目录所在的目录、目录名前缀以及目录属性。如果不指定目录,则在默认的临时文件目录中创建目录。目录名前缀可以用于帮助识别临时目录的用途。例如,前缀可以是"temp_dir_",这样创建的临时目录可能命名为 "temp_dir_12345"。
Path tempFile = null; try { tempFile = Files.createTempFile(null, "temp_", ".txt"); // 对临时文件进行操作 //... } catch (IOException e) { e.printStackTrace(); } finally { if (tempFile!= null) { try { // 在finally块中删除临时文件和目录 Files.delete(tempFile); } catch (IOException e) { e.printStackTrace(); } } }
⚠️注意事项:
临时文件和目录的清理:临时文件和目录在使用完毕后应该及时清理,以避免占用系统资源。可以在程序结束时手动删除临时文件和目录,或者使用一些工具类来自动清理临时资源。例如,可以在finally块中删除临时文件和目录。
并发安全:在多线程环境中,使用临时文件和目录时需要注意并发安全问题。确保多个线程不会同时尝试创建相同名称的临时文件或目录,以免导致冲突。可以使用同步机制或者为每个线程创建独立的临时文件和目录来避免并发问题。
平台差异:临时文件和目录的创建可能会受到操作系统的限制和差异。不同的操作系统可能有不同的临时文件目录位置和权限设置。在编写跨平台的程序时,需要考虑这些差异。
可以将一个文件从源路径复制到目标路径。例如:
Path sourcePath = Paths.get("source.txt"); Path targetPath = Paths.get("target.txt"); try { Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING); System.out.println("文件复制成功!"); } catch (IOException e) { e.printStackTrace(); } Files.copy(fromPath,toPath,StandardCopyoption.REPLACE_EXISTING,StandardCopyOption.COPY_ATTRIBUTES);
如果目标文件存在的话,copy 方法会失败。如果你希望覆盖一个已存在的目标文件,请使用 StandardCopyoption.REPLACE_EXISTING 选项。如果你希望复制所有的文件属性,请使用 StandardCopyoption.COPY_ATTRIBUTES 选项。你也可以同时提供这两个选项,如下所示:
Files.copy(fromPath, toPath, StandardCopyoption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES);
将一个文件从源路径移动到目标路径 (即复制并删除原来的文件),注意,你还可以使用该方法移动一个空的目录。例如:
Path sourcePath = Paths.get("source.txt"); Path targetPath = Paths.get("newLocation/target.txt"); try { Files.move(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING); System.out.println("文件移动成功!"); } catch (IOException e) { e.printStackTrace(); }
如果目标目录存在的话,move 方法会失败。你可以指定使用原子方式来执行移动操作。这样要么移动操作成功完成,要么源文件依然存在。要指定原子操作可以使用 StandardCopyoption.ATOMIC_MOVE 选项:
Files.move(fromPath, toPath, StandardCopyoption.ATOMIC_MOVE);
删除一个文件或目录。例如:
Path filePath = Paths.get("fileToDelete.txt"); try { Files.delete(filePath); System.out.println("文件删除成功!"); } catch (IOException e) { e.printStackTrace(); }
如果文件不存在,则该方法会抛出一个异常,因此你可能希望使用另一个方法:
boolean deleted = Files.deleteIfExists(path);
该删除方法也可以用于删除一个空目录。
⚠️注意:没有直接删除或复制非空目录的方法。要实现这些操作,请参考FileVisitor接口的API文档。
返回文件的大小(以字节为单位)。例如:
long size = Files.size(Paths.get("/path/to/file.txt"));
返回文件的最后修改时间。例如:
FileTime lastModifiedTime = Files.getLastModifiedTime(Paths.get("/path/to/file.txt"));
设置文件的最后修改时间。例如:
Files.setLastModifiedTime(Paths.get("/path/to/file.txt"), FileTime.fromMillis(System.currentTimeMillis()));
更多关于 Files 类的用法,请参考 API 文档。