NIO编程基础
一、什么是NIO编程?
jdk1.4之后在IO的基础上进行改进的。
NIO中有一个非阻塞IO,面向缓冲区的,NIO效率高。类似火车那种
IO是阻塞IO:面向流的
程序读取文件InputStream,类似水管一样传输。
NIO图示:
IO图示:
NIO和IO区别:
二、直接缓冲区与 非直接缓冲区
缓冲区分为两种:
直接缓冲去:
非直接缓冲区:
存放在物理内存比jvm缓冲区要快。
三、NIO(new IO)核心是通道+缓冲区(存放数据)
NIO:保留了IO本质操作读写操作,是非阻塞IO.
NIO概念
四、使用buffer存储数据
Buffer可以用的类型有:
byteBuffer
LongBuffer
IntegeBuffer
FloatBuffer
DoubleBuffer
三个参数:
position:表示当前缓冲区操作的位置
limit:表示当前缓冲区可用大小
capacity:表示当前缓冲区的大小,定义好了就不可以变了
打印出buffer三个参数的案例:
package com.leeue.nio
import java.nio.Buffer
import java.nio.ByteBuffer
import org.junit.Test
public class NioBufferDemo01 {
@Test
public void test1() {
//初始化byteBuffer大小
ByteBuffer byteBuffer = ByteBuffer.allocate(1024)
System.out.println(byteBuffer.position())
System.out.println(byteBuffer.limit())
System.out.println(byteBuffer.capacity())
System.out.println("往buffer存放数据")
byteBuffer.put("abcd1".getBytes())
System.out.println(byteBuffer.position())
System.out.println(byteBuffer.limit())
System.out.println(byteBuffer.capacity())
//要开启读取模式
byteBuffer.flip()
System.out.println("position:"+byteBuffer.position())
System.out.println("读取数据....")
byte[] bytes = new byte[byteBuffer.limit()]
//将数据放到bytes里面
byteBuffer.get(bytes)
System.out.println(new String(bytes,0,bytes.length))
System.out.println(byteBuffer.position())
System.out.println(byteBuffer.limit())
System.out.println(byteBuffer.capacity())
System.out.println("重复读取....")
//只有设置下才能重复读 又会将position设置为上次postion的起始位置
byteBuffer.rewind()
byte[] bytes2 = new byte[byteBuffer.limit()]
//将数据放到bytes里面
byteBuffer.get(bytes2)
System.out.println(new String(bytes2,0,bytes2.length))
System.out.println(byteBuffer.position())
System.out.println(byteBuffer.limit())
System.out.println(byteBuffer.capacity())
//清空缓冲区,只是把数据下标重置了,数据还是在内存里,清空缓冲区又叫数据被遗忘
System.out.println("清空缓存......")
byteBuffer.clear()
System.out.println(byteBuffer.position())
System.out.println(byteBuffer.limit())
System.out.println(byteBuffer.capacity())
System.out.println((char)byteBuffer.get())
}
}
五、标记make与重置rest用法
package com.leeue.nio;
import java.nio.ByteBuffer;
/**
*
* @classDesc: 功能描述:(Buffer中 make与rest方法)
* @author:<a href="[email protected]">李月</a>
* @Version:v1.0
* @createTime:2018年7月30日 上午10:40:59
*/
public class NIOMakeAndRest {
public static void main(String[] args) {
ByteBuffer byteBuffer = ByteBuffer.allocate(10);
String str = "abcd";
byteBuffer.put(str.getBytes());
byteBuffer.flip();
byte[] bytes = new byte[byteBuffer.limit()];
byteBuffer.mark();
byteBuffer.get(bytes, 0, 2);
System.out.println(new String(bytes, 0, 2));
System.out.println(byteBuffer.position());
System.out.println("---------重置--------");
byteBuffer.reset();
byteBuffer.get(bytes, 0, 2);
System.out.println(new String(bytes, 0, 2));
System.out.println(byteBuffer.position());
}
}
六、缓冲区
缓冲区分为两种:
第一种:直接缓冲区,存放在物理内存中 效率高 不需要来回拷贝
第二种:非直接缓冲区:主要存放在jvm中 效率低 需要来回拷贝
存放在物理内存中比jvm缓冲区中快
非直接缓冲区
直接缓冲区
非直接缓冲区与直接缓冲区那种更安全?
非直接缓冲区更安全
直接缓冲区占内存
七、通道(Channel)的原理获取
案例代码
package com.leeue.nio;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import org.junit.Test;
/**
*
* @classDesc: 功能描述:(实际操作直接缓冲区与非直接缓冲区比较)
* @author:<a href="[email protected]">李月</a>
* @Version:v1.0
* @createTime:2018年7月30日 上午11:11:29
*/
public class NIOChannelDemo03 {
/**
* 非直接缓冲区读写操作
* @throws IOException
*/
@Test
public void test01() throws IOException {
FileInputStream fileInputStream = new FileInputStream("1.png");
FileOutputStream fileOutputStream = new FileOutputStream("1Copy.png");
FileChannel inchannel = fileInputStream.getChannel();
FileChannel outchannel = fileOutputStream.getChannel();
ByteBuffer buf = ByteBuffer.allocate(1024);
while(inchannel.read(buf)!=-1) {
buf.flip();
outchannel.write(buf);
buf.clear();
}
inchannel.close();
outchannel.close();
fileInputStream.close();
fileOutputStream.close();
}
/**
* 直接缓冲区操作
* @throws IOException
*/
@Test
public void test02() throws IOException{
FileChannel inChannel = FileChannel.open(Paths.get("1.png"), StandardOpenOption.READ);
FileChannel outChannel = FileChannel.open(Paths.get("1CP.png"), StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE);
MappedByteBuffer inMappedByte = inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());
MappedByteBuffer outMappedByte = outChannel.map(MapMode.READ_WRITE, 0, inChannel.size());
byte[] dsf = new byte[inMappedByte.limit()];
inMappedByte.get(dsf);
outMappedByte.put(dsf);
inChannel.close();
outChannel.close();
System.out.println("直接缓冲区操作完毕");
}
}
八、分散读取聚集写入
package com.leeue.nio;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
*
* @classDesc: 功能描述:(分散读取 聚集写入)
* @author:<a href="[email protected]">李月</a>
* @Version:v1.0
* @createTime:2018年7月30日 上午11:53:49
*/
public class NIOScatteringDemo04 {
public static void main(String[] args) throws IOException{
RandomAccessFile raf = new RandomAccessFile("test.txt", "rw");
FileChannel channel = raf.getChannel();
ByteBuffer buffer1 = ByteBuffer.allocate(100);
ByteBuffer buffer2 = ByteBuffer.allocate(1024);
ByteBuffer[] buffers = { buffer1, buffer2 };
channel.read(buffers);
for (ByteBuffer byteBuffer : buffers) {
byteBuffer.flip();
}
System.out.println(new String(buffers[0].array(), 0, buffers[0].limit()));
System.out.println("*****************");
System.out.println(new String(buffers[1].array(), 1, buffers[1].limit()));
System.out.println("聚集读取.....");
RandomAccessFile raf2 = new RandomAccessFile("test2.txt", "rw");
FileChannel channel2 = raf2.getChannel();
channel2.write(buffers);
raf2.close();
raf.close();
}
}
九、字符集Charset
编码:字符串-->字节数组
解码:字节数组-->字符串
package com.leeue.nio;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
/**
*
* @classDesc: 功能描述:(字符编码案例)
* @author:<a href="[email protected]">李月</a>
* @Version:v1.0
* @createTime:2018年7月30日 下午1:51:17
*/
public class CharsetDemo05 {
public static void main(String[] args) throws CharacterCodingException {
Charset charset = Charset.forName("GBK");
CharsetEncoder ce = charset.newEncoder();
CharsetDecoder cd = charset.newDecoder();
CharBuffer charBuffer = CharBuffer.allocate(1024);
charBuffer.put("欢迎访我的博客");
charBuffer.flip();
ByteBuffer buffer = ce.encode(charBuffer);
System.out.println("****加密后的字符串****");
for(int i = 0; i < 12; i++) {
System.out.println(buffer.get());
}
buffer.flip();
CharBuffer decode = cd.decode(buffer);
System.out.println(decode.toString());
}
}