Java 基础之 IO 和 NIO 补完

本贴最后更新于 2671 天前,其中的信息可能已经东海扬尘

Java Stream,File,IO

java 包之 java.io

java 包之 java.nio

15 Java NIO Path

  • 翻译自:15Java NIO Path
  • Java 的 java.nio.file.Path 接口是 JavaNIO 2 update 的一部分,在 Java6 和 Java7 中得到更新。Java path 接口在 java7 中被加入到 Java NIO 中。Path 接口位于 java.nio.file 包中,所以 Java Path 接口的全名是:java.nio.file.Path。
  • 一个 Java Path 接口代表了一个文件系统中的 path 路径。path 路径可以指向文件或目录。一个路径可以是绝对路径也可以是相对路径。一个绝对路径是从文件系统根目录指向该文件或路径的全路径。一个相对路径是指相对于其他路径一个文件或目录的相对路径。相对路径可能比较费解,不用担心,我会在该文中详细介绍。
  • 对于操作系统中的系统路径这样的环境变量不要疑惑,java Path 接口跟它们没有关系。
  • 在很多方面 java.nio.file.Path 和 java.io.File 类是类似的,在一些地方你可以使用 Path 接口来代替 File 类,但是也有一些不同。

1. 创建 Path 实例

  • 你可以使用 java.nio.file.Paths 类的静态方法 Paths.get()来创建一个 java.nio.file.Path 的实例:
import java.nio.file.Path; import java.nio.file.Paths; public class PathExample { public static void main(String[] args) { Path path = Paths.get("c:\\data\\myfile.txt"); } }
  • Paths.get()方法是创建 Path 实例的工厂方法。

2. 创建一个绝对路径 Path 实例

  • Windows 文件系统下的绝对路径:
Path path = Paths.get("c:\\data\\myfile.txt");
  • 类 Unix 操作系统下的绝对路径:
Path path = Paths.get("/home/jakobjenkov/myfile.txt"); //如果你在windows上这么使用,会表示当前系统分区下的路径,如:C:/home/jakobjenkov/myfile.txt

3. 创建一个相对路径 Path 实例

  • 相对路径需要一个 basepath 和 relativepath 来创建:
Path projects = Paths.get("d:\\data", "projects"); Path file = Paths.get("d:\\data", "projects\\a-project\\myfile.txt");
  • 可以使用'.','..'来创建路径实例:
Path currentDir = Paths.get("."); System.out.println(currentDir.toAbsolutePath());

4. Path.normalize()

String originalPath = "d:\\data\\projects\\a-project\\..\\another-project"; Path path1 = Paths.get(originalPath); System.out.println("path1 = " + path1); Path path2 = path1.normalize(); System.out.println("path2 = " + path2); path1 = d:\data\projects\a-project\..\another-project path2 = d:\data\projects\another-project

16. Java NIO Files

  • 翻译自:16Java NIO Files
  • java.nio.file.Files 类提供了多种方法来操作文件。

1. Files.exists()

  • LinkOption.NOFOLLOW_LINKS 表示文件存在,但是不能是链接形式的。
Path path = Paths.get("data/logging.properties"); boolean pathExists = Files.exists(path, new LinkOption[]{ LinkOption.NOFOLLOW_LINKS});

2. Files.createDirectory()

Path path = Paths.get("data/subdir"); try { Path newDir = Files.createDirectory(path); } catch(FileAlreadyExistsException e){ // the directory already exists. } catch (IOException e) { //something else went wrong e.printStackTrace(); }

3. Files.copy()

Path sourcePath = Paths.get("data/logging.properties"); Path destinationPath = Paths.get("data/logging-copy.properties"); try { Files.copy(sourcePath, destinationPath); } catch(FileAlreadyExistsException e) { //destination file already exists } catch (IOException e) { //something else went wrong e.printStackTrace(); }

4. Overwriting Existing Files

  • 通过复制选项来覆盖已经存在的 Files
Path sourcePath = Paths.get("data/logging.properties"); Path destinationPath = Paths.get("data/logging-copy.properties"); try { Files.copy(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING); } catch(FileAlreadyExistsException e) { //destination file already exists } catch (IOException e) { //something else went wrong e.printStackTrace(); }

5. Files.move()

  • java.io.File 有方法 renameTo() ,Files 可以 Files.move()
Path sourcePath = Paths.get("data/logging-copy.properties"); Path destinationPath = Paths.get("data/subdir/logging-moved.properties"); try { Files.move(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING); } catch (IOException e) { //moving file failed. e.printStackTrace(); }

6. Files.delete()

Path path = Paths.get("data/subdir/logging-moved.properties"); try { Files.delete(path); } catch (IOException e) { //deleting file failed e.printStackTrace(); }

7. Files.walkFileTree()

  • Files.walkFileTree()用来递归遍历文件目录,有 Path 实例和 FileVisitor 来做参数。
  • FileVisitor 接口有如下形式:
public interface FileVisitor { public FileVisitResult preVisitDirectory( Path dir, BasicFileAttributes attrs) throws IOException; public FileVisitResult visitFile( Path file, BasicFileAttributes attrs) throws IOException; public FileVisitResult visitFileFailed( Path file, IOException exc) throws IOException; public FileVisitResult postVisitDirectory( Path dir, IOException exc) throws IOException { }
  • FileVisitor 有一个简单实现 SimpleFileVisitor 类:
Files.walkFileTree(path, new FileVisitor<Path>() { @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { System.out.println("pre visit dir:" + dir); return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { System.out.println("visit file: " + file); return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { System.out.println("visit file failed: " + file); return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { System.out.println("post visit directory: " + dir); return FileVisitResult.CONTINUE; } }); FileVisitResult的集合有: CONTINUE 表示继续 TERMINATE 表示停止 SKIP_SIBLINGS 表示继续但是不再便利兄弟目录 SKIP_SUBTREE 表示继续但是不再便利子目录

8. Searching For Files

  • 下面可以实现 SimpleFileVisitor 来查找文件:
Path rootPath = Paths.get("data"); String fileToFind = File.separator + "README.txt"; try { Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { String fileString = file.toAbsolutePath().toString(); //System.out.println("pathString = " + fileString); if(fileString.endsWith(fileToFind)){ System.out.println("file found at path: " + file.toAbsolutePath()); return FileVisitResult.TERMINATE; } return FileVisitResult.CONTINUE; } }); } catch(IOException e){ e.printStackTrace(); }

9. Deleting Directories Recursively

Path rootPath = Paths.get("data/to-delete"); try { Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { System.out.println("delete file: " + file.toString()); Files.delete(file); return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { Files.delete(dir); System.out.println("delete dir: " + dir.toString()); return FileVisitResult.CONTINUE; } }); } catch(IOException e){ e.printStackTrace(); }

10. Additional Methods in the Files Class

  • Files 类有很多其他方法,如 creating symbolic links, determining the file size, setting file permissions 等。参考 java 文档。

17. Java NIO AsynchronousFileChannel

  • java7 中 AsynchronousFileChannel 加入到了 java NIO 的包中。AsynchronousFileChannels 使得异步读写文件实现。

1. Creating an AsynchronousFileChannel

Path path = Paths.get("data/test.xml"); AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ);

2. Reading Data

  • Reading Data Via a Future
Future<Integer> operation = fileChannel.read(buffer, 0); AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ); ByteBuffer buffer = ByteBuffer.allocate(1024); long position = 0; Future<Integer> operation = fileChannel.read(buffer, position); // Of course, this is not a very efficient use of the CPU - but somehow you need to wait until the read operation has completed. while(!operation.isDone()); buffer.flip(); byte[] data = new byte[buffer.limit()]; buffer.get(data); System.out.println(new String(data)); buffer.clear();
  • Reading Data Via a CompletionHandler
fileChannel.read(buffer, position, buffer, new CompletionHandler<Integer, ByteBuffer>() { //Once the read operation finishes the CompletionHandler's completed() method will be called. @Override public void completed(Integer result, ByteBuffer attachment) { System.out.println("result = " + result); attachment.flip(); byte[] data = new byte[attachment.limit()]; attachment.get(data); System.out.println(new String(data)); attachment.clear(); } //If the read operation fails, the failed() method of the CompletionHandler will get called instead. @Override public void failed(Throwable exc, ByteBuffer attachment) { } });

3. Writing Data

  • Writing Data Via a Future
Path path = Paths.get("data/test-write.txt"); //If the file does not exist the write() method will throw a java.nio.file.NoSuchFileException . if(!Files.exists(path)){ Files.createFile(path); } AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE); ByteBuffer buffer = ByteBuffer.allocate(1024); long position = 0; buffer.put("test data".getBytes()); buffer.flip(); Future<Integer> operation = fileChannel.write(buffer, position); buffer.clear(); while(!operation.isDone()); System.out.println("Write done");
  • Writing Data Via a CompletionHandler
Path path = Paths.get("data/test-write.txt"); if(!Files.exists(path)){ Files.createFile(path); } AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE); ByteBuffer buffer = ByteBuffer.allocate(1024); long position = 0; buffer.put("test data".getBytes()); buffer.flip(); fileChannel.write(buffer, position, buffer, new CompletionHandler<Integer, ByteBuffer>() { @Override public void completed(Integer result, ByteBuffer attachment) { System.out.println("bytes written: " + result); } @Override public void failed(Throwable exc, ByteBuffer attachment) { System.out.println("Write failed"); exc.printStackTrace(); } });
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3194 引用 • 8214 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...