NIO-缓存-通道-选择器
来源:互联网 发布:淘宝网店海报分辨率 编辑:程序博客网 时间:2024/06/07 06:32
NIO
1、通道
2、缓冲区 (间接内存-非直接缓冲区,直接内存--直接缓冲区)
3、阻塞通道示例
4、非阻塞通道示例 ----选择器(多路复用IO模型)
---主要是将 通道 和 selector·选择器 进行绑定,基于IO的多路复用模型,使用一个或多进行轮询注册通道,根据状态返回值进行操作
5、管道
6、Path、Paths、Files 类
1、通道
1、NIO中的Channel的主要实现有:
FileChannel:用于读取、写入、映射和操作文件的通道。
DatagramChannel:通过UDP 读写网络中的数据通道。
SocketChannel:通过TCP 读写网络中的数据。
ServerSocketChannel:可以监听新进来的TCP 连接,对每一个新进来的连接都会创建一个SocketChannel。
这里看名字就可以猜出个所以然来:分别可以对应文件IO、UDP和TCP(Server和Client)
2、获取通道的方式:
获取通道的一种方式是对支持通道的对象调用
getChannel() 方法。支持通道的类如下:
FileInputStream
FileOutputStream
RandomAccessFile
DatagramSocket
Socket
ServerSocket
获取通道的其他方式是使用Files 类的静态方法newByteChannel() 获取字节通道。或者通过通道的静态方法open() 打开并返回指定通道。
关键点:代码示例中有体现:
1、通道的分散和聚集Scatter/Gatter
分散(scatter)从Channel中读取是指在读操作时将读取的数据写入多个buffer中。因此,Channel将从Channel中读取的数据“分散(scatter)”到多个Buffer中。
聚集(gather)写入Channel是指在写操作时将多个buffer的数据写入同一个Channel,因此,Channel 将多个Buffer中的数据“聚集(gather)”后发送到Channel。
scatter / gather经常用于需要将传输的数据分开处理的场合,例如传输一个由消息头和消息体组成的消息,你可能会将消息体和消息头分散到不同的buffer中,这样你可以方便的处理消息头和消息体。(应用场景)
注重提到的应用点,请求头+请求体 用不同的buffer传输
ther() { ByteBuffer header = ByteBuffer.allocate(10); ByteBuffer body = ByteBuffer.allocate(10); byte [] b1 = {'0', '1'}; byte [] b2 = {'2', '3'}; header.put(b1); body.put(b2); ByteBuffer [] buffs = {header, body}; try { FileOutputStream os = new FileOutputStream("src/scattingAndGather.txt"); FileChannel channel = os.getChannel(); channel.write(buffs); } catch (IOException e) { e.printStackTrace(); } }}
2、 通道之间的数据传输(直接缓冲区) transferFrom() transferTo() //示例代码中有体现
代码示例:
/* * 一、通道(Channel):用于源节点与目标节点的连接。在 Java NIO 中负责缓冲区中数据的传输。Channel 本身不存储数据,因此需要配合缓冲区进行传输。 * * 二、通道的主要实现类 * java.nio.channels.Channel 接口: * |--FileChannel * |--SocketChannel * |--ServerSocketChannel * |--DatagramChannel * * 三、获取通道 * 1. Java 针对支持通道的类提供了 getChannel() 方法 * 本地 IO: * FileInputStream/FileOutputStream * RandomAccessFile * * 网络IO: * Socket * ServerSocket * DatagramSocket * * 2. 在 JDK 1.7 中的 NIO.2 针对各个通道提供了静态方法 open() * 3. 在 JDK 1.7 中的 NIO.2 的 Files 工具类的 newByteChannel() * * 四、通道之间的数据传输 * transferFrom() * transferTo() * * 五、分散(Scatter)与聚集(Gather) * 分散读取(Scattering Reads):将通道中的数据分散到多个缓冲区中 * 聚集写入(Gathering Writes):将多个缓冲区中的数据聚集到通道中 * * 六、字符集:Charset * 编码:字符串 -> 字节数组 * 解码:字节数组 -> 字符串 * */public class TestChannel {//字符集@Testpublic void test6() throws IOException{Charset cs1 = Charset.forName("GBK");//获取编码器CharsetEncoder ce = cs1.newEncoder();//获取解码器CharsetDecoder cd = cs1.newDecoder();CharBuffer cBuf = CharBuffer.allocate(1024);cBuf.put("尚硅谷威武!");cBuf.flip();//编码ByteBuffer bBuf = ce.encode(cBuf);for (int i = 0; i < 12; i++) {System.out.println(bBuf.get());}//解码bBuf.flip();CharBuffer cBuf2 = cd.decode(bBuf);System.out.println(cBuf2.toString());System.out.println("------------------------------------------------------");Charset cs2 = Charset.forName("GBK");bBuf.flip();CharBuffer cBuf3 = cs2.decode(bBuf);System.out.println(cBuf3.toString());}@Testpublic void test5(){Map<String, Charset> map = Charset.availableCharsets();Set<Entry<String, Charset>> set = map.entrySet();for (Entry<String, Charset> entry : set) {System.out.println(entry.getKey() + "=" + entry.getValue());}}//分散和聚集@Testpublic void test4() throws IOException{RandomAccessFile raf1 = new RandomAccessFile("1.txt", "rw");//1. 获取通道FileChannel channel1 = raf1.getChannel();//2. 分配指定大小的缓冲区ByteBuffer buf1 = ByteBuffer.allocate(100);ByteBuffer buf2 = ByteBuffer.allocate(1024);//3. 分散读取ByteBuffer[] bufs = {buf1, buf2};channel1.read(bufs);for (ByteBuffer byteBuffer : bufs) {byteBuffer.flip();}System.out.println(new String(bufs[0].array(), 0, bufs[0].limit()));System.out.println("-----------------");System.out.println(new String(bufs[1].array(), 0, bufs[1].limit()));//4. 聚集写入RandomAccessFile raf2 = new RandomAccessFile("2.txt", "rw");FileChannel channel2 = raf2.getChannel();channel2.write(bufs);}//通道之间的数据传输(直接缓冲区)@Testpublic void test3() throws IOException{FileChannel inChannel = FileChannel.open(Paths.get("d:/1.mkv"), StandardOpenOption.READ);FileChannel outChannel = FileChannel.open(Paths.get("d:/2.mkv"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);//inChannel.transferTo(0, inChannel.size(), outChannel);outChannel.transferFrom(inChannel, 0, inChannel.size());inChannel.close();outChannel.close();}//使用直接缓冲区完成文件的复制(内存映射文件)@Testpublic void test2() throws IOException{//2127-1902-1777long start = System.currentTimeMillis();FileChannel inChannel = FileChannel.open(Paths.get("d:/1.mkv"), StandardOpenOption.READ);FileChannel outChannel = FileChannel.open(Paths.get("d:/2.mkv"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);//内存映射文件MappedByteBuffer inMappedBuf = inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());MappedByteBuffer outMappedBuf = outChannel.map(MapMode.READ_WRITE, 0, inChannel.size());//直接对缓冲区进行数据的读写操作byte[] dst = new byte[inMappedBuf.limit()];inMappedBuf.get(dst);outMappedBuf.put(dst);inChannel.close();outChannel.close();long end = System.currentTimeMillis();System.out.println("耗费时间为:" + (end - start));}//利用通道完成文件的复制(非直接缓冲区)@Testpublic void test1(){//10874-10953long start = System.currentTimeMillis();FileInputStream fis = null;FileOutputStream fos = null;//①获取通道FileChannel inChannel = null;FileChannel outChannel = null;try {fis = new FileInputStream("d:/1.mkv");fos = new FileOutputStream("d:/2.mkv");inChannel = fis.getChannel();outChannel = fos.getChannel();//②分配指定大小的缓冲区ByteBuffer buf = ByteBuffer.allocate(1024);//③将通道中的数据存入缓冲区中while(inChannel.read(buf) != -1){buf.flip(); //切换读取数据的模式//④将缓冲区中的数据写入通道中outChannel.write(buf);buf.clear(); //清空缓冲区}} catch (IOException e) {e.printStackTrace();} finally {if(outChannel != null){try {outChannel.close();} catch (IOException e) {e.printStackTrace();}}if(inChannel != null){try {inChannel.close();} catch (IOException e) {e.printStackTrace();}}if(fos != null){try {fos.close();} catch (IOException e) {e.printStackTrace();}}if(fis != null){try {fis.close();} catch (IOException e) {e.printStackTrace();}}}long end = System.currentTimeMillis();System.out.println("耗费时间为:" + (end - start));}}
2、缓冲区:
1、缓冲区中的四个核心属性:
capacity : 容量,表示缓冲区中最大存储数据的容量。一旦声明不能改变。
limit : 界限,表示缓冲区中可以操作数据的大小。(limit后数据不能进行读写)
position : 位置,表示缓冲区中正在操作数据的位置。
mark : 标记,表示记录当前 position的位置。可以通过reset()恢复到mark的位置
0 <= mark (jdk java.nio.Buffer源码中默认为-1) <= position <= limit <= capacity
2、直接缓冲区与非直接缓冲区:
非直接缓冲区:通过 allocate() 方法分配缓冲区,将缓冲区建立在 JVM 的内存中
直接缓冲区:通过 allocateDirect() 方法分配直接缓冲区,将缓冲区建立在物理内存中。可以提高效率
直接缓冲区开辟堆外内存(jvm的直接内存区域)MappedByteBuffer类相当于一个资源映射文件,
滤过堆内存空间,直接对堆外内存进行操作,提高效率。
NIO 的 Buffer 还提供了一个可以直接访问系统物理内存的类 DirectBuffer。DirectBuffer 继承自 ByteBuffer,但和普通的 ByteBuffer 不同。普通的 ByteBuffer 仍然在 JVM 堆上分配空间,其最大内存受到最大堆的限制,而 DirectBuffer 直接分配在物理内存上,并不占用堆空间。在对普通的 ByteBuffer 访问时,系统总是会使用一个“内核缓冲区”进行间接的操作。而 DirectrBuffer 所处的位置,相当于这个“内核缓冲区”。因此,使用 DirectBuffer 是一种更加接近系统底层的方法,所以,它的速度比普通的 ByteBuffer 更快。DirectBuffer 相对于 ByteBuffer 而言,读写访问速度快很多,但是创建和销毁 DirectrBuffer 的花费却比 ByteBuffer 高
参考:http://blog.csdn.net/phil_code/article/details/69056086 理解
代码示例:
/* * 一、缓冲区(Buffer):在 Java NIO 中负责数据的存取。缓冲区就是数组。用于存储不同数据类型的数据 * * 根据数据类型不同(boolean 除外),提供了相应类型的缓冲区: * ByteBuffer * CharBuffer * ShortBuffer * IntBuffer * LongBuffer * FloatBuffer * DoubleBuffer * * 上述缓冲区的管理方式几乎一致,通过 allocate() 获取缓冲区 * * 二、缓冲区存取数据的两个核心方法: * put() : 存入数据到缓冲区中 * get() : 获取缓冲区中的数据 * * 三、缓冲区中的四个核心属性: * capacity : 容量,表示缓冲区中最大存储数据的容量。一旦声明不能改变。 * limit : 界限,表示缓冲区中可以操作数据的大小。(limit 后数据不能进行读写) * position : 位置,表示缓冲区中正在操作数据的位置。 * * mark : 标记,表示记录当前 position 的位置。可以通过 reset() 恢复到 mark 的位置 * * 0 <= mark <= position <= limit <= capacity * * 四、直接缓冲区与非直接缓冲区: * 非直接缓冲区:通过 allocate() 方法分配缓冲区,将缓冲区建立在 JVM 的内存中 * 直接缓冲区:通过 allocateDirect() 方法分配直接缓冲区,将缓冲区建立在物理内存中。可以提高效率 */public class TestBuffer {@Testpublic void test3(){//分配直接缓冲区ByteBuffer buf = ByteBuffer.allocateDirect(1024);System.out.println(buf.isDirect());}@Testpublic void test2(){String str = "abcde";ByteBuffer buf = ByteBuffer.allocate(1024);buf.put(str.getBytes());buf.flip();byte[] dst = new byte[buf.limit()];buf.get(dst, 0, 2);System.out.println(new String(dst, 0, 2));System.out.println(buf.position());//mark() : 标记buf.mark();buf.get(dst, 2, 2);System.out.println(new String(dst, 2, 2));System.out.println(buf.position());//reset() : 恢复到 mark 的位置buf.reset();System.out.println(buf.position());//判断缓冲区中是否还有剩余数据if(buf.hasRemaining()){//获取缓冲区中可以操作的数量System.out.println(buf.remaining());}}@Testpublic void test1(){String str = "abcde";//1. 分配一个指定大小的缓冲区ByteBuffer buf = ByteBuffer.allocate(1024);System.out.println("-----------------allocate()----------------");System.out.println(buf.position());System.out.println(buf.limit());System.out.println(buf.capacity());//2. 利用 put() 存入数据到缓冲区中buf.put(str.getBytes());System.out.println("-----------------put()----------------");System.out.println(buf.position());System.out.println(buf.limit());System.out.println(buf.capacity());//3. 切换读取数据模式buf.flip();System.out.println("-----------------flip()----------------");System.out.println(buf.position());System.out.println(buf.limit());System.out.println(buf.capacity());//4. 利用 get() 读取缓冲区中的数据byte[] dst = new byte[buf.limit()];buf.get(dst);System.out.println(new String(dst, 0, dst.length));System.out.println("-----------------get()----------------");System.out.println(buf.position());System.out.println(buf.limit());System.out.println(buf.capacity());//5. rewind() : 可重复读buf.rewind();System.out.println("-----------------rewind()----------------");System.out.println(buf.position());System.out.println(buf.limit());System.out.println(buf.capacity());//6. clear() : 清空缓冲区. 但是缓冲区中的数据依然存在,但是处于“被遗忘”状态buf.clear();System.out.println("-----------------clear()----------------");System.out.println(buf.position());System.out.println(buf.limit());System.out.println(buf.capacity());System.out.println((char)buf.get());}}
3、阻塞通道示例
/* * 一、使用 NIO 完成网络通信的三个核心: * * 1. 通道(Channel):负责连接 * * java.nio.channels.Channel 接口: * |--SelectableChannel * |--SocketChannel * |--ServerSocketChannel * |--DatagramChannel * * |--Pipe.SinkChannel * |--Pipe.SourceChannel * * 2. 缓冲区(Buffer):负责数据的存取 * * 3. 选择器(Selector):是 SelectableChannel 的多路复用器。用于监控 SelectableChannel 的 IO 状况 * */public class TestBlockingNIO {//客户端@Testpublic void client() throws IOException{//1. 获取通道SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898));FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);//2. 分配指定大小的缓冲区ByteBuffer buf = ByteBuffer.allocate(1024);//3. 读取本地文件,并发送到服务端while(inChannel.read(buf) != -1){buf.flip();sChannel.write(buf);buf.clear();}//4. 关闭通道inChannel.close();sChannel.close();}//服务端@Testpublic void server() throws IOException{//1. 获取通道ServerSocketChannel ssChannel = ServerSocketChannel.open();FileChannel outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);//2. 绑定连接ssChannel.bind(new InetSocketAddress(9898));//3. 获取客户端连接的通道SocketChannel sChannel = ssChannel.accept();//4. 分配指定大小的缓冲区ByteBuffer buf = ByteBuffer.allocate(1024);//5. 接收客户端的数据,并保存到本地while(sChannel.read(buf) != -1){buf.flip();outChannel.write(buf);buf.clear();}//6. 关闭通道sChannel.close();outChannel.close();ssChannel.close();}}
public class TestBlockingNIO2 {//客户端@Testpublic void client() throws IOException{SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898));FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);ByteBuffer buf = ByteBuffer.allocate(1024);while(inChannel.read(buf) != -1){buf.flip();sChannel.write(buf);buf.clear();}sChannel.shutdownOutput(); //通知服务器发送完毕//接收服务端的反馈int len = 0;while((len = sChannel.read(buf)) != -1){buf.flip();System.out.println(new String(buf.array(), 0, len));buf.clear();}inChannel.close();sChannel.close();}//服务端@Testpublic void server() throws IOException{ServerSocketChannel ssChannel = ServerSocketChannel.open();FileChannel outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);ssChannel.bind(new InetSocketAddress(9898));SocketChannel sChannel = ssChannel.accept();ByteBuffer buf = ByteBuffer.allocate(1024);while(sChannel.read(buf) != -1){buf.flip();outChannel.write(buf);buf.clear();}//发送反馈给客户端buf.put("服务端接收数据成功".getBytes());buf.flip();sChannel.write(buf);sChannel.close();outChannel.close();ssChannel.close();}}
4、非阻塞通道示例 ----选择器(多路复用IO模型)
/* * 一、使用 NIO 完成网络通信的三个核心: * * 1. 通道(Channel):负责连接 * * java.nio.channels.Channel 接口: * |--SelectableChannel * |--SocketChannel * |--ServerSocketChannel * |--DatagramChannel * * |--Pipe.SinkChannel * |--Pipe.SourceChannel * * 2. 缓冲区(Buffer):负责数据的存取 * * 3. 选择器(Selector):是 SelectableChannel 的多路复用器。用于监控 SelectableChannel 的 IO 状况 * */public class TestNonBlockingNIO {//客户端@Testpublic void client() throws IOException{//1. 获取通道SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898));//2. 切换非阻塞模式sChannel.configureBlocking(false);//3. 分配指定大小的缓冲区ByteBuffer buf = ByteBuffer.allocate(1024);//4. 发送数据给服务端Scanner scan = new Scanner(System.in);while(scan.hasNext()){String str = scan.next();buf.put((new Date().toString() + "\n" + str).getBytes());buf.flip();sChannel.write(buf);buf.clear();}//5. 关闭通道sChannel.close();}//服务端@Testpublic void server() throws IOException{//1. 获取通道ServerSocketChannel ssChannel = ServerSocketChannel.open();//2. 切换非阻塞模式ssChannel.configureBlocking(false);//3. 绑定连接ssChannel.bind(new InetSocketAddress(9898));//4. 获取选择器Selector selector = Selector.open();//5. 将通道注册到选择器上, 并且指定“监听接收事件”ssChannel.register(selector, SelectionKey.OP_ACCEPT);//6. 轮询式的获取选择器上已经“准备就绪”的事件while(selector.select() > 0){//7. 获取当前选择器中所有注册的“选择键(已就绪的监听事件)”Iterator<SelectionKey> it = selector.selectedKeys().iterator();while(it.hasNext()){//8. 获取准备“就绪”的是事件SelectionKey sk = it.next();//9. 判断具体是什么事件准备就绪if(sk.isAcceptable()){//10. 若“接收就绪”,获取客户端连接SocketChannel sChannel = ssChannel.accept();//11. 切换非阻塞模式sChannel.configureBlocking(false);//12. 将该通道注册到选择器上sChannel.register(selector, SelectionKey.OP_READ);}else if(sk.isReadable()){//13. 获取当前选择器上“读就绪”状态的通道SocketChannel sChannel = (SocketChannel) sk.channel();//14. 读取数据ByteBuffer buf = ByteBuffer.allocate(1024);int len = 0;while((len = sChannel.read(buf)) > 0 ){buf.flip();System.out.println(new String(buf.array(), 0, len));buf.clear();}}//15. 取消选择键 SelectionKeyit.remove();}}}}
public class TestNonBlockingNIO2 {@Testpublic void send() throws IOException{DatagramChannel dc = DatagramChannel.open();dc.configureBlocking(false);ByteBuffer buf = ByteBuffer.allocate(1024);Scanner scan = new Scanner(System.in);while(scan.hasNext()){String str = scan.next();buf.put((new Date().toString() + ":\n" + str).getBytes());buf.flip();dc.send(buf, new InetSocketAddress("127.0.0.1", 9898));buf.clear();}dc.close();}@Testpublic void receive() throws IOException{DatagramChannel dc = DatagramChannel.open();dc.configureBlocking(false);dc.bind(new InetSocketAddress(9898));Selector selector = Selector.open();dc.register(selector, SelectionKey.OP_READ);while(selector.select() > 0){Iterator<SelectionKey> it = selector.selectedKeys().iterator();while(it.hasNext()){SelectionKey sk = it.next();if(sk.isReadable()){ByteBuffer buf = ByteBuffer.allocate(1024);dc.receive(buf);buf.flip();System.out.println(new String(buf.array(), 0, buf.limit()));buf.clear();}}it.remove();}}}
public class ServerConnect{ private static final int BUF_SIZE=1024; private static final int PORT = 8080; private static final int TIMEOUT = 3000; public static void main(String[] args) { selector(); } public static void selector() { Selector selector = null; ServerSocketChannel ssc = null; try{ selector = Selector.open(); ssc= ServerSocketChannel.open(); ssc.socket().bind(new InetSocketAddress(PORT)); ssc.configureBlocking(false); ssc.register(selector, SelectionKey.OP_ACCEPT); while(true){ if(selector.select(TIMEOUT) == 0){ System.out.println("=="); continue; } Iterator<SelectionKey> iter = selector.selectedKeys().iterator(); while(iter.hasNext()){ SelectionKey key = iter.next(); if(key.isAcceptable()){ handleAccept(key); } if(key.isReadable()){ handleRead(key); } if(key.isWritable() && key.isValid()){ handleWrite(key); } if(key.isConnectable()){ System.out.println("isConnectable = true"); } iter.remove(); } } }catch(IOException e){ e.printStackTrace(); }finally{ try{ if(selector!=null){ selector.close(); } if(ssc!=null){ ssc.close(); } }catch(IOException e){ e.printStackTrace(); } } } public static void handleAccept(SelectionKey key) throws IOException{ ServerSocketChannel ssChannel = (ServerSocketChannel)key.channel(); SocketChannel sc = ssChannel.accept(); sc.configureBlocking(false); sc.register(key.selector(), SelectionKey.OP_READ,ByteBuffer.allocateDirect(BUF_SIZE)); } public static void handleRead(SelectionKey key) throws IOException{ SocketChannel sc = (SocketChannel)key.channel(); ByteBuffer buf = (ByteBuffer)key.attachment(); long bytesRead = sc.read(buf); while(bytesRead>0){ buf.flip(); while(buf.hasRemaining()){ System.out.print((char)buf.get()); } System.out.println(); buf.clear(); bytesRead = sc.read(buf); } if(bytesRead == -1){ sc.close(); } } public static void handleWrite(SelectionKey key) throws IOException{ ByteBuffer buf = (ByteBuffer)key.attachment(); buf.flip(); SocketChannel sc = (SocketChannel) key.channel(); while(buf.hasRemaining()){ sc.write(buf); } buf.compact(); }}
5、管道(Pipe)
Java NIO 管道是2个线程之间的单向数据连接。Pipe有一个source通道和一个sink通道。数据会被写到sink通道,从source通道读取。
public class TestPipe {@Testpublic void test1() throws IOException{//1. 获取管道Pipe pipe = Pipe.open();//2. 将缓冲区中的数据写入管道ByteBuffer buf = ByteBuffer.allocate(1024);Pipe.SinkChannel sinkChannel = pipe.sink();buf.put("通过单向管道发送数据".getBytes());buf.flip();sinkChannel.write(buf);//3. 读取缓冲区中的数据Pipe.SourceChannel sourceChannel = pipe.source();buf.flip();int len = sourceChannel.read(buf);System.out.println(new String(buf.array(), 0, len));sourceChannel.close();sinkChannel.close();}}
public static void method1(){ Pipe pipe = null; ExecutorService exec = Executors.newFixedThreadPool(2); try{ pipe = Pipe.open(); final Pipe pipeTemp = pipe; exec.submit(new Callable<Object>(){ @Override public Object call() throws Exception { Pipe.SinkChannel sinkChannel = pipeTemp.sink();//向通道中写数据 while(true){ TimeUnit.SECONDS.sleep(1); String newData = "Pipe Test At Time "+System.currentTimeMillis(); ByteBuffer buf = ByteBuffer.allocate(1024); buf.clear(); buf.put(newData.getBytes()); buf.flip(); while(buf.hasRemaining()){ System.out.println(buf); sinkChannel.write(buf); } } } }); exec.submit(new Callable<Object>(){ @Override public Object call() throws Exception { Pipe.SourceChannel sourceChannel = pipeTemp.source();//向通道中读数据 while(true){ TimeUnit.SECONDS.sleep(1); ByteBuffer buf = ByteBuffer.allocate(1024); buf.clear(); int bytesRead = sourceChannel.read(buf); System.out.println("bytesRead="+bytesRead); while(bytesRead >0 ){ buf.flip(); byte b[] = new byte[bytesRead]; int i=0; while(buf.hasRemaining()){ b[i]=buf.get(); System.out.printf("%X",b[i]); i++; } String s = new String(b); System.out.println("=================||"+s); bytesRead = sourceChannel.read(buf); } } } }); }catch(IOException e){ e.printStackTrace(); }finally{ exec.shutdown(); } }
6、Path、Paths、Files 类
public class TestNIO_2 {//自动资源管理:自动关闭实现 AutoCloseable 接口的资源@Testpublic 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){}}/*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 对象 */@Testpublic void test7() throws IOException{SeekableByteChannel newByteChannel = Files.newByteChannel(Paths.get("1.jpg"), StandardOpenOption.READ);DirectoryStream<Path> newDirectoryStream = Files.newDirectoryStream(Paths.get("e:/"));for (Path path : newDirectoryStream) {System.out.println(path);}}/*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 指定的文件相关联的属性。 */@Testpublic void test6() throws IOException{Path path = Paths.get("e:/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常用方法:Path copy(Path src, Path dest, CopyOption … how) : 文件的复制Path createDirectory(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 指定文件的大小 */@Testpublic 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);}@Testpublic 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);}@Testpublic 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);}/*Paths 提供的 get() 方法用来获取 Path 对象:Path get(String first, String … more) : 用于将多个字符串串连成路径。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 对象的字符串表示形式 */@Testpublic void test2(){Path path = Paths.get("e:/nio/hello.txt");System.out.println(path.getParent());System.out.println(path.getRoot());//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);System.out.println(path.toString());}@Testpublic void test1(){Path path = Paths.get("e:/", "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));}}}
- NIO-缓存-通道-选择器
- java nio学习:缓冲区、通道和选择器
- Java NIO系列4:通道和选择器
- Java NIO系列4:通道和选择器
- Java NIO 选择器(Selector)与通道(Channel) 原理
- NIO缓存区(4)之通道、管道
- nio-选择器
- nio选择器
- NIO系列(二)——Channel通道复制和Selector选择器
- NIO channel Socket通道
- JAVA NIO Socket通道
- java nio 通道(一)
- java nio 通道(二)
- Java NIO 通道
- NIO(JDK1.4)--通道
- NIO通道和缓冲区
- NIO - Socket 通道
- NIO中通道(Channel)
- opengl superbible 6th mac 10.12 xcode配置环境及新建工程
- 解决虚拟机中文本选中后自动被复制到剪贴板的问题
- Android动画 SVG VectorDrawable 基础一
- UGUI鼠标事件绑定+鼠标长按
- 管道
- NIO-缓存-通道-选择器
- HEVC专业术语对译
- Android动画 SVG VectorDrawable 基础二
- 数据挖掘考试重点(条理版)
- 基于Python3的phantomJs+Selenium动态网页爬取技术
- F1V3.0-图形-自动成图-系统图算法介绍
- 【编程语言】C#中字符串的内存分配
- JVM里java对象的创建及内存分配和访问定位
- Linux下安装python-opencv ,亲测可用