NIO2的关键基础类:
Path:该类中的方法可以用来获取路径信息,访问该路径中的各元素,将路径转换为其他形式,或提取路径中的一部分。有的方法还可以匹配路径字串以及移除路径中的冗余项
Paths:工具类,提供一个返回一个路径的的辅助方法,比如get(String first,String ... more)和get(URI uri)
FileSystem:与文件系统交互的类,无论是默认的文件系统还是通过其URI获取的可选文件系统
FileSystems:工具类,提供各种方法,比如其中用于返回默认文件系统的FileSystems.getDefault()
在NIO2中path或paths的各种方法抛出的受检异常只有IOException
1.创建Path
创建Path方法:
a/Paths.get(String path)
b/FileSystems.getDefault().getPath(String path)
两者是等价的
2.从path中获取信息
path.getFileName--获取当前文件名
path.getNameCount--获取当前文件数量
path.getParent--获取当前路径的父路径
path.getRoot--获取根路径
path.subpath(beginIndex,endIndex)--获取根路径与当前路径之间的子路径
path.toAbsolutePath--把相对路径转换为绝对路径
3.移除冗余项
normalize()方法和toRealPath()可以去除冗余项,得到真正的path
4.转换Path
resolve():合并路径
relativize():计算两个路径之间的路径
5.Java File类与NIO2 Path
File类的toPath()方法可以将File类转化为NIO2的Path
Path类的toFile()方法可以将Path类转化为File
6.在目录中查找文件
示例代码如下:
Path:该类中的方法可以用来获取路径信息,访问该路径中的各元素,将路径转换为其他形式,或提取路径中的一部分。有的方法还可以匹配路径字串以及移除路径中的冗余项
Paths:工具类,提供一个返回一个路径的的辅助方法,比如get(String first,String ... more)和get(URI uri)
FileSystem:与文件系统交互的类,无论是默认的文件系统还是通过其URI获取的可选文件系统
FileSystems:工具类,提供各种方法,比如其中用于返回默认文件系统的FileSystems.getDefault()
在NIO2中path或paths的各种方法抛出的受检异常只有IOException
1.创建Path
创建Path方法:
a/Paths.get(String path)
b/FileSystems.getDefault().getPath(String path)
两者是等价的
2.从path中获取信息
path.getFileName--获取当前文件名
path.getNameCount--获取当前文件数量
path.getParent--获取当前路径的父路径
path.getRoot--获取根路径
path.subpath(beginIndex,endIndex)--获取根路径与当前路径之间的子路径
path.toAbsolutePath--把相对路径转换为绝对路径
3.移除冗余项
normalize()方法和toRealPath()可以去除冗余项,得到真正的path
4.转换Path
resolve():合并路径
relativize():计算两个路径之间的路径
5.Java File类与NIO2 Path
File类的toPath()方法可以将File类转化为NIO2的Path
Path类的toFile()方法可以将Path类转化为File
6.在目录中查找文件
示例代码如下:
Path dir=Paths.get("F:/Tmp/Learn");
try(DirectoryStream<Path> stream=Files.newDirectoryStream(dir,"*.txt")){
for(Path entry:stream){
System.out.println(entry.getFileName());
}
}catch(IOException e){
System.out.println(e.getMessage());
}
7.遍历目录树
示例代码如下:
示例代码如下:
Path dir=Paths.get("F:/Tmp");
Files.walkFileTree(dir,new FindJavaVisitor());
private static class FindJavaVisitor{
@override
public FileVisitResult visitFile(Path File,BasicFileAttributes attrs){
if(file.toString().endsWith(".txt"){
System.out.println(file.getFileName());
}
return FileVisitResult.CONTINUE;
}
}
8.创建和删除文件
创建文件:Files.createFile(Path path);
还可以在创建文件时加入attr属性,指定只读、可写、可执行
删除文件:Files.delete(Path path);
9.文件的移动和复制
Files.copy(Path source,Path target);
复制属性包括:REPLACE_EXISTING(覆盖替换),COPY_ATTRIBUTES(复制文件属性),ATOMIC_MOVE(确保两边操作都成功,否则回滚)
移动方法名为move,其他与复制同
10.文件属性
为了支持文件系统特定的文件属性,java7允许文件系统提供者实现FileAttributeView和BasicFileAttributes接口
Files.readAttributes(Path path,String pattern);--获取当前路径下文件属性
11.快速读写文件
示例代码如下
Read:
创建文件:Files.createFile(Path path);
还可以在创建文件时加入attr属性,指定只读、可写、可执行
删除文件:Files.delete(Path path);
9.文件的移动和复制
Files.copy(Path source,Path target);
复制属性包括:REPLACE_EXISTING(覆盖替换),COPY_ATTRIBUTES(复制文件属性),ATOMIC_MOVE(确保两边操作都成功,否则回滚)
移动方法名为move,其他与复制同
10.文件属性
为了支持文件系统特定的文件属性,java7允许文件系统提供者实现FileAttributeView和BasicFileAttributes接口
Files.readAttributes(Path path,String pattern);--获取当前路径下文件属性
11.快速读写文件
示例代码如下
Read:
Path path=Paths.get("F:/Tmp");
try(BufferedReader
br=Files.newBufferedReader(path,StandardCharsets.UTF_8);){
String line;
while((line=br.readLine())!=null){
//doSomething
}
}
Write:
Path path=Paths.get("F:/Tmp");
try(BufferedWriter
bw=Files.newBufferedWriter(dir,StandardCharsets.UTF_8,StandardOpenOption.WRITE)){
//doSomething
}
读取全部字符串:
List<String>lines=Files.readAllLines(dir,StandardCharsets.UTF_8);
读取全部字节:
byte[]bytes=Files.readAllBytes(dir);
List<String>lines=Files.readAllLines(dir,StandardCharsets.UTF_8);
读取全部字节:
byte[]bytes=Files.readAllBytes(dir);
12.文件修改通知
监测变化->检查shutdown标志->得到下一个key及其事件->检查是否为变化事件->重置检测key
示例代码如下:
监测变化->检查shutdown标志->得到下一个key及其事件->检查是否为变化事件->重置检测key
示例代码如下:
try{
WatchService watcher=FileSystems.getDefault().newWatchService();
Path dir=Paths.get("F:/Tmp");
WatchKey key=dir.register(watcher,ENTRY_MODIFY);
while(!shutdown){
key=watcher.take();
for(WatchEvent<?>event:key.pollEvents()){
if(event.kind()==ENTRY_MODIFY){
//doSomething
}
}
key.reset();
}catch(IOException|InterruptedException e){
System.out.println(e.getMessage());
}
其他可监测事件有:ENTRY_CREATE,ENTRY_DELETE和OVERFLOW
13.异步IO操作
java7中有3个异步通道:
AsynchronousFileChannel--用于文件IO
AsynchronousSocketChannel--用于套接字IO
AsynchronousServerSocketChannel--用于套接字接受异步连接
使用新的IO api时主要有两种形式:将来式和回调式
A.将来式
当希望由主线程发起IO操作并轮询等待结果时,一般用将来式异步处理
通常会用Future的get()方法在异步IO操作完成时获取其结果。(主线程可以在读取数据的同时继续完成其他操作)
示例代码如下:
13.异步IO操作
java7中有3个异步通道:
AsynchronousFileChannel--用于文件IO
AsynchronousSocketChannel--用于套接字IO
AsynchronousServerSocketChannel--用于套接字接受异步连接
使用新的IO api时主要有两种形式:将来式和回调式
A.将来式
当希望由主线程发起IO操作并轮询等待结果时,一般用将来式异步处理
通常会用Future的get()方法在异步IO操作完成时获取其结果。(主线程可以在读取数据的同时继续完成其他操作)
示例代码如下:
try{
Path path=Paths.get("F:/Tmp");
AsynchronousFileChannel channel=AsynchronousSocketChannel.open(path);
ByteBuffer buffer=ByteBuffer.allocate(100_000);//读取100000字节
Future<Integer>result=channel.read(buffer,0);
while(!result.isDone()){
//doSomething else
}
Integer bytesRead=result.get();
System.out.println("Bytes Read["+bytesRead+"]");
}catch(IOException|ExecutionException|InterruptedException e){
System.out.println(e.getMessage());
}
AsynchronousFileChannel会关联线程池,它的任务是接收IO处理事件,并分发给处理通道中IO操作结果的结果处理器。跟通道中发起的IO操作关联的结果处理器确保是由线程池中的某个线程产生的。如果在创建AsynchronousSocketChannel时没有为其指定线程池(可能会和其他通道共享),默认线程池是由AsynchronousFileChannelGroup类定义的系统属性进行配置的。
B.回调式
在异步事件刚一成功或失败并需要马上采取行动时,一般会用回调式。
示例代码如下:
B.回调式
在异步事件刚一成功或失败并需要马上采取行动时,一般会用回调式。
示例代码如下:
try{
Path path=Paths.get("F:/Tmp");
AsynchronousFileChannel channel=AsynchronousFileChannel.open(path);
ByteBuffer buffer=ByteBuffer.allocate(100_000);
channel.read(buffer,0,buffer,new CompletionHandler<Integer,ByteBuffer>(){
public void completed(Integer result,ByteBuffer attachment){
System.out.println("Bytes read["+result+"]");
}
public void failed(Throwable exception,ByteBuffer attachment){
System.out.println(exception.getMessage());
}
});
}catch(IOException e){
System.out.println(e.getMessage());
}
14.Socket和channel的整合
套接字:两个机器间通信的端点
NetworkChannel示例代码:(NetworkChannel的出现使多播操作成为可能)
套接字:两个机器间通信的端点
NetworkChannel示例代码:(NetworkChannel的出现使多播操作成为可能)
SelectorProvider provider=SelectorProvider.provider();
try{
NetworkChannel socketChannel=provider.openSocketChannel();
SocketAddress address=new InetSocketAddress(3080);
socketChannel=socketChannel.bind(address);
Set<SocketOption<?>>socketOptions=socketChannel.supportedOptions();
System.out.println(socketOptions.toString());
socketChannel.setOption(StandardSocketOptions.IP_TOS,3);
Boolean keepAlive=socketChannel.getOption(StandardSocketOptions.SO_KEEPALIVE);
//...
}catch(IOException e){
System.out.println(e.getMessage());
}
MulticastChannel:
多播(组播)表示一对多的网络通讯,通常用来指代IP多播。其基本前提是将一个包发送到一个组播地址,然后网络对该包进行复制,分发给所有接收端(注册到组播地址中)。为了对NetworkChannel加入多播组,java7提供了一个新接口java.nio.channels.MulticastChannel及其默认实现类DatagramChannel,即可以轻松对多播组发送和接收数据
示例代码如下:
选择网络接口->打开dc->将通道设置为多播->加入多播组
多播(组播)表示一对多的网络通讯,通常用来指代IP多播。其基本前提是将一个包发送到一个组播地址,然后网络对该包进行复制,分发给所有接收端(注册到组播地址中)。为了对NetworkChannel加入多播组,java7提供了一个新接口java.nio.channels.MulticastChannel及其默认实现类DatagramChannel,即可以轻松对多播组发送和接收数据
示例代码如下:
选择网络接口->打开dc->将通道设置为多播->加入多播组
try{
NetworkInterface networkInterface=NetworkInterface.getByName("netl");
DatagramChannel dc=DatagramChannel.open(StandardProtocolFamily.INET);
dc.setOption(StandardSocketOptions.SO_REUSEADDR,true);
dc.bind(new InetSocketAddress(8080));
dc.setOption(StandardSocketOptions.IP_MULTICAST_IF,networkInterface);
InetAddress group=InetAddress.getByName("180.90.4.12");
MembershipKey key=dc.join(group,networkInterface);
}catch(IOException e){
System.out.println(e.getMessage());
}