- 什么是“流”
所谓流就是有产出数据能力的东东(学名就是“数据源”,“输入流”)或者接收数据的能力的东东(学名就是“数据接收端”,“输出流”,通信里面一般把这种东西叫“信宿”吧),一个文件可读,那么它就有产出数据的能力;一个文件可写,那么它就有接收数据的能力。
java下的InputStream就是"输入流"的最顶层类,OutputStream 就是“输出流”的最顶层类。
其实这里名字有点混淆,因为:按说能产出数据的应该叫“输出***” ,能接收数据的应该叫“输入***” 。其实之所以按上面说的命名是因为,我们总是站在“内存”的角度上说的,你有产出数据的能力,那么你产出的数据应该“流入”到我内存里来,而你能接收数据,那我内存就把数据“输出”给你好啦。
- Buffer的存在
java的nio里面有Buffer,这是个缓存器。缓冲器对于数据的高速I/O很关键。ByteBuffer是将数据移进移出通道的唯一方式(尽管你可以使用as***方法,利用视图缓冲器将基本类型数据移进移出ByteBuffer)
在java里面这样做:输入流用.getChannel() 或者输出流.getChannel()方法获取通道,然后通道再和缓冲器交互,调用输入流的通道的read方法可以给缓冲器里放入数据,调用输出流的通道的write方法可以获取缓冲器里的数据。
缓冲区有两个指示位置: postion(当前位置) 和limit(上限位置)
当你要获取get() 缓冲区里的内容时,你需要上限位置设为当前位置,把当前位置设为0。 可以调用flip方法
java api文档里这样写的:in.read(buf); // 输入流给缓冲器里放入数据 buf.flip(); // 缓冲器的“当前位置”和“上界位置”重置 out.write(buf); // 输出流读取刚刚输入流给缓冲器的数据
个人感觉吧,缓冲器就是有两个指针的一段内存。
还有rewind() 方法:它其实只是重置了“当前位置”,将当前位置重置为0,而上限位置保持不变
- ByteBuffer的静态方法wrap
其实我一直不是很理解这个静态方法,因为往缓冲器里放东西直接put就好啦,干嘛需要这个方法呢?
目前的理解是这样:
使用put方法之前需要先allocate() 分配内存空间,但是wrap不需要,直接wrap即可。1 ByteBuffer bb = ByteBuffer.allocate(1024); 2 IntBuffer ib = bb.asIntBuffer(); 3 ib.put(new int[]{11,43,56,35,118,29}); 4 System.out.println("the third int is:"+ib.get(2)); 5 ib.put(2,78); 6 ib.flip();//如果你不flip的话,输出结果就全是零,因为是当前位置之后读取的 7 while(ib.hasRemaining()){ 8 System.out.println(ib.get()); 9 } 10 String ss = "只是为了测试"; 11 ByteBuffer sbb; 12 try { 13 sbb = ByteBuffer.wrap(ss.getBytes("UTF-16"));//这里就直接wrap了,并不需要事先分配allocate出空间 14 //sbb.flip(); 15 System.out.println(sbb.asCharBuffer());//输出结果是:?只是为了测试 不是想要的结果也 16 } catch (UnsupportedEncodingException e) { 17 // TODO Auto-generated catch block 18 e.printStackTrace(); 19 }
一般来说呢,allocate,put,flip,get搭配使用;wrap,rewind,get配合使用(因为你wrap分配的就是字节数组那么大的空间,所以直接rewind只改变当前位置即可,不需要改变limit位置,所以不用flip啦)
Buffer有四个索引:position,limit,capacity,mark。上面已经说了两个。
未完待续