随着JDK 7 的发布,Java对NIO进行了极大的扩展,增强了对文件处理和文件系统特性的支持,以至于我们称他们为NIO.2。因为NIO 提供的一些功能,NIO已经成为文件处理中越来越重要的部分。
NIO2.0引入了新的异步通道的概念,并提供了异步文件通道和异步套接字通道的实现。
异步通道提供两种方式获取操作结果:
- 通过java.util.concurrent.Future类来表示异步操作的结果;
- 在执行异步操作的时候传入一个java.nio.channels。
NIO2.0的异步套接字通道是真正的异步非阻塞I/O,它对应UNIX网络编程中的事件驱动I/O(AIO),它不需要通过多路复用器(Selector)对注册的通道进行轮询操作即可实现异步读写,从而简化了NIO的编程模型。
【1】Path 与Paths
java.nio.file.Path 接口代表一个平台无关的平台路径,描述了目录结构中文件的位置。
Paths 提供的get() 方法用来获取Path 对象:
Path get(String first, String … more) : 用于将多个字符串串连成路径。
e.g:
FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);
Path常用方法:
方法 | 描述 |
---|---|
boolean endsWith(String path) | 判断是否以path 路径结束 |
boolean startsWith(String path) | 判断是否以path 路径开始 |
boolean isAbsolute() | 判断是否是绝对路径 |
Path getFileName() | 返回与调用Path 对象关联的文件名 |
Path getName(int idx) | 返回的指定索引位置idx 的路径名称 |
int getNameCount() | 返回Path 根目录后面元素的数量 |
Path getParent() | 返回Path对象包含整个路径,不包含Path 对象指定的文件路径 |
Path getRoot() | 返回调用Path 对象的根路径 |
Path resolve(Path p) | 将相对路径解析为绝对路径 |
Path toAbsolutePath() | 作为绝对路径返回调用Path 对象 |
String toString() | 返回调用Path 对象的字符串表示形式 |
测试实例一如下:
@Test
public void test1(){
Path path = Paths.get("d:/", "nio/hello.txt");
System.out.println(path.endsWith("hello.txt"));
System.out.println(path.startsWith("e:/"));
System.out.println(path.isAbsolute());
System.out.println(path.getFileName());
for (int i = 0; i < path.getNameCount(); i++) {
System.out.println(path.getName(i));
}
}
测试结果如下:
true
false
true
hello.txt
nio
hello.txt
注意,并不会校验"d:/nio/hello.txt"
究竟是否存在!
测试实例二如下:
@Test
public void test2(){
Path path = Paths.get("e:/nio/hello.txt");
System.out.println(path.getParent());
//e:\nio
System.out.println(path.getRoot());
//e:\
// Path newPath = path.resolve("e:/hello.txt");
// System.out.println(newPath);
Path path2 = Paths.get("1.jpg");
Path newPath = path2.toAbsolutePath();
System.out.println(newPath);
//D:\workspace_idea\hh-test\nio\1.jpg
System.out.println(path.toString());
//e:\nio\hello.txt
}
【2】Files 类
java.nio.file.Files 用于操作文件或目录的工具类。
Files常用方法:
- Path copy(Path src, Path dest, CopyOption … how) : 文件的复制
- PathcreateDirectory(Path path, FileAttribute<?> … attr) : 创建一个目录
- Path createFile(Path path, FileAttribute<?> … arr) : 创建一个文件
- void delete(Path path) : 删除一个文件
- Path move(Path src, Path dest, CopyOption…how) : 将src 移动到dest 位置
- long size(Path path) : 返回path 指定文件的大小
文件复制实例如下:
@Test
public void test3() throws IOException{
Path path1 = Paths.get("e:/nio/hello.txt");
Path path2 = Paths.get("e:/nio/hello2.txt");
Files.copy(path1, path2, StandardCopyOption.REPLACE_EXISTING);
}
创建删除文件实例如下:
@Test
public void test4() throws IOException{
Path dir = Paths.get("e:/nio/nio2");
// Files.createDirectory(dir);
Path file = Paths.get("e:/nio/nio2/hello3.txt");
// Files.createFile(file);
Files.deleteIfExists(file);
}
移动文件/查看文件大小实例如下:
@Test
public void test5() throws IOException{
Path path1 = Paths.get("e:/nio/hello2.txt");
Path path2 = Paths.get("e:/nio/hello7.txt");
System.out.println(Files.size(path2));
// Files.move(path1, path2, StandardCopyOption.ATOMIC_MOVE);
}
Files常用方法:用于判断
- boolean exists(Path path, LinkOption … opts) : 判断文件是否存在
- boolean isDirectory(Path path, LinkOption … opts) : 判断是否是目录
- boolean isExecutable(Path path) : 判断是否是可执行文件
- boolean isHidden(Path path) : 判断是否是隐藏文件
- boolean isReadable(Path path) : 判断文件是否可读
- boolean isWritable(Path path) : 判断文件是否可写
- boolean notExists(Path path, LinkOption … opts) : 判断文件是否不存在
public static <A extends BasicFileAttributes> A readAttributes(Path path,Class<A> type,LinkOption... options)
: 获取与path 指定的文件相关联的属性。
实例如下:
@Test
public void test6() throws IOException{
Path path = Paths.get("d:/nio/hello7.txt");
// System.out.println(Files.exists(path, LinkOption.NOFOLLOW_LINKS));
BasicFileAttributes readAttributes = Files.readAttributes(path, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
System.out.println(readAttributes.creationTime());
System.out.println(readAttributes.lastModifiedTime());
DosFileAttributeView fileAttributeView = Files.getFileAttributeView(path, DosFileAttributeView.class, LinkOption.NOFOLLOW_LINKS);
fileAttributeView.setHidden(false);
}
Files常用方法:用于操作内容
- SeekableByteChannel newByteChannel(Path path, OpenOption…how) : 获取与指定文件的连接,how 指定打开方式。
- DirectoryStream newDirectoryStream(Path path) : 打开path 指定的目录
- InputStream newInputStream(Path path, OpenOption…how):获取InputStream 对象
- OutputStream newOutputStream(Path path, OpenOption…how) : 获取OutputStream 对象
测试实例如下:
@Test
public void test7() throws IOException{
SeekableByteChannel newByteChannel = Files.newByteChannel(Paths.get("1.jpg"), StandardOpenOption.READ);
DirectoryStream<Path> newDirectoryStream = Files.newDirectoryStream(Paths.get("d:/"));
for (Path path : newDirectoryStream) {
System.out.println(path);
}
}
【3】自动资源管理
Java 7 增加了一个新特性,该特性提供了另外一种管理资源的方式,这种方式能自动关闭文件。这个特性有时被称为自动资源管理(Automatic Resource Management, ARM),该特性以try 语句的扩展版为基础。
自动资源管理主要用于,当不再需要文件(或其他资源)时,可以防止无意中忘记释放它们。
自动资源管理基于try 语句的扩展形式:
try(需要关闭的资源声明){
//可能发生异常的语句
}catch(异常类型变量名){
//异常的处理语句
}finally{
//一定执行的语句
}
当try 代码块结束时,自动释放资源。因此不需要显示的调用close() 方法。该形式也称为“带资源的try 语句”。
注意:
①try 语句中声明的资源被隐式声明为final ,资源的作用局限于带资源的try 语句
②可以在一条try 语句中管理多个资源,每个资源以“;” 隔开即可。
③需要关闭的资源,必须实现了AutoCloseable 接口或其自接口Closeable
测试实例如下:
@Test
public void test8(){
try(FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
FileChannel outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE, StandardOpenOption.CREATE)){
ByteBuffer buf = ByteBuffer.allocate(1024);
inChannel.read(buf);
}catch(IOException e){
e.printStackTrace();
}
}
NIO项目源码:GitHub下载地址。