@huangyichun
        
        2017-08-30T07:56:22.000000Z
        字数 7503
        阅读 1056
    I/O
 
原来I/O是单向的,面向流的 
NIO是双向的 
 

 
 
 

import org.junit.Test;import java.nio.ByteBuffer;/*** 一、 缓冲区(buffer):在Java NIO中负责数据的存取,缓冲区就是数组,用于存储不同数据类型的数据** 根据数据类型不同(boolean除外),提供了相应类型的缓冲区:* ByteBuffer* CharBuffer* ShortBuffer* IntBuffer* LongBuffer* FloatBuffer* DoubleBuffer** 上述缓存区的管理几乎一致,通过allocate()获取缓冲区** 二、缓存区存取数据的两个核心方法* put():存入数据到缓冲区中* get(): 获取缓冲区中的数据** 三、缓冲区中的四个核心属性** private int mark = -1;标记:表示记录当前position的位置。可以通过reset()恢复mark位置* private int position = 0; 位置:表示缓冲区中正在操作数据的位置* private int limit; 界限:表示缓存区中可以操作数据的大小(limit)后面的数据不能进行读写* private int capacity; 容量:表示缓存区中最大存储数据容量,一旦声明不能改变** 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("position: "+buf.position());//mark()标记buf.mark();buf.get(dst, 2, 2);System.out.println(new String(dst, 0, 4));System.out.println("position: "+buf.position());buf.reset();System.out.println("position: "+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("position: "+buf.position());System.out.println("limit: " + buf.limit());System.out.println("capacity: " + buf.capacity());System.out.println("----------------put()------------");//2.利用put()方法存入数据到缓冲区中——写数据模式buf.put(str.getBytes());System.out.println("position: "+buf.position());System.out.println("limit: " + buf.limit());System.out.println("capacity: " + buf.capacity());System.out.println("----------------flip()------------");//3.切换成读取数据模式buf.flip();System.out.println("position: "+buf.position());System.out.println("limit: " + buf.limit());System.out.println("capacity: " + buf.capacity());System.out.println("----------------get()------------");//4利用get()方法读取缓冲区的数据byte[] dst = new byte[buf.limit()];buf.get(dst);System.out.println(new String(dst, 0, dst.length));System.out.println("position: "+buf.position());System.out.println("limit: " + buf.limit());System.out.println("capacity: " + buf.capacity());System.out.println("----------------rewind()------------");//5.rewind() 可重复读数据buf.rewind();System.out.println("position: "+buf.position());System.out.println("limit: " + buf.limit());System.out.println("capacity: " + buf.capacity());System.out.println("----------------clear()------------");//6.clear():清空缓冲区,但是缓冲区中的数据依然存在,但是出于"被遗忘"状态buf.clear();System.out.println("position: "+buf.position());System.out.println("limit: " + buf.limit());System.out.println("capacity: " + buf.capacity());System.out.println((char)buf.get(1));}}

import org.junit.Test;import java.io.*;import java.nio.ByteBuffer;import java.nio.CharBuffer;import java.nio.MappedByteBuffer;import java.nio.channels.FileChannel;import java.nio.channels.FileChannel.MapMode;import java.nio.charset.CharacterCodingException;import java.nio.charset.Charset;import java.nio.charset.CharsetDecoder;import java.nio.charset.CharsetEncoder;import java.nio.file.Paths;import java.nio.file.StandardOpenOption;import java.util.Arrays;import java.util.Map;import java.util.stream.Stream;/*** 一、通道(Channel):用于源节点与目标节点的链接。在Java NIO中负责缓冲区中数据的传输* Channel本身不存储数据,因此需要配合缓冲区进行传输。* <p>* 二、通道的主要实现类* java.nio.channels.Channel接口:* |--FileChannel* |--SocketChannel* |--ServerSocketChannel* |--DatagramChannel* 三、获取通道* 1. Java支持通道的类提供了getChannel()方法* 本地IO:* FileInputStream/FileOutputStream* RandomAccessFile* <p>* 网络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 Writers):将多个缓冲区中的数据聚集到通道中** 六、字符集:Charset* 编码: 字符串——>字节数组* 解码: 字节数组——>字符串**/public class TestChannel {//字符集@Testpublic void test7() throws CharacterCodingException {Charset cs1 = Charset.forName("GBK");//获取编码器CharsetEncoder ce = cs1.newEncoder();//获取解码器CharsetDecoder cd = cs1.newDecoder();CharBuffer cBuf = CharBuffer.allocate(1024);cBuf.put("尚硅谷威武!");cBuf.flip();//切换读//编码ByteBuffer byteBuffer = ce.encode(cBuf);for(int i=0; i<cBuf.limit()*2; i++){System.out.println(byteBuffer.get());}//解码byteBuffer.flip();CharBuffer cBuf2 = cd.decode(byteBuffer);System.out.println(cBuf2.toString());}@Testpublic void test6(){Map<String, Charset> map = Charset.availableCharsets();map.forEach((x,y)->{System.out.println(x+"="+y);});}//分散和聚集@Testpublic void test5() throws IOException {RandomAccessFile raf = new RandomAccessFile("学习清单.txt","rw");//1.获取通道FileChannel channel = raf.getChannel();//2.分配指定大小的缓冲区ByteBuffer buf1 = ByteBuffer.allocate(100);ByteBuffer buf2 = ByteBuffer.allocate(1024);//3.分散读取ByteBuffer[] bufs = {buf1, buf2};channel.read(bufs);Arrays.stream(bufs).forEach(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);channel.close();channel2.close();}//通道之间的数据传输(直接缓冲区,内存映射文件)@Testpublic void test4() throws IOException {FileChannel inChannel = FileChannel.open(Paths.get("E:/1.zip"),StandardOpenOption.READ);FileChannel outChannel = FileChannel.open(Paths.get("E:/2.zip"),StandardOpenOption.READ, StandardOpenOption.WRITE,StandardOpenOption.CREATE);// inChannel.transferTo(0, inChannel.size(), outChannel);outChannel.transferFrom(inChannel, 0, inChannel.size());inChannel.close();outChannel.close();}//3. I/O操作@Testpublic void test3() throws IOException { //9755long start = System.currentTimeMillis();FileInputStream fis = new FileInputStream("E:/1.zip");FileOutputStream fos = new FileOutputStream("E:/2.zip");BufferedInputStream bufis = new BufferedInputStream(fis);byte[] bts = new byte[1024];while(bufis.read(bts) != -1){fos.write(bts);}bufis.close();fis.close();fos.close();long end = System.currentTimeMillis();System.out.println("耗费时间为:" + (end-start));}//2.使用直接缓冲区完成文件复制(内存映射文件)@Testpublic void test2() throws IOException {//2457long start = System.currentTimeMillis();FileChannel inChannel = FileChannel.open(Paths.get("E:/1.zip"), StandardOpenOption.READ);FileChannel outChannel = FileChannel.open(Paths.get("E:/2.zip"), 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));}//1.利用通道完成文件的复制(非直接缓冲区)@Testpublic void test1() throws IOException {//9942long start = System.currentTimeMillis();FileInputStream fis = new FileInputStream("E:/1.zip");FileOutputStream fos = new FileOutputStream("E:/2.zip");//获取通道FileChannel inChannel = fis.getChannel();FileChannel outChannel = fos.getChannel();//分配指定大小的缓存区ByteBuffer buf = ByteBuffer.allocate(1024);//将通道中的数据存入缓冲区中while (inChannel.read(buf) != -1) {//将缓冲区中的数据写入通道中buf.flip(); //切换成读取数据的模式outChannel.write(buf);buf.clear();//清空缓冲区}outChannel.close();inChannel.close();fos.close();fis.close();long end = System.currentTimeMillis();System.out.println("耗费时间为:" + (end-start));}}
