JDK1.4出的
BIO 比较 NIO
1,是流的方式,块的方式。
2,阻塞,非阻塞
3,基于字节流或者是字符流,基于Channel和Buffer 管道和缓冲区。selector 是基于事件的监听。
每个channel和buffer是对应的
selector根据事件,切换到不同的channel中,所以channel会注册到selector中,event 也是事先定义好的。
所有数据的读写都是需要通过bufffer的,提高效率。
BIO中只能是一种流,而NIO是双向的。
Buffer的基本使用
package bio;
import java.nio.IntBuffer;
public class MyBuffer {
public static void main(String[] args) {
IntBuffer allocate = IntBuffer.allocate(1024);
for (int i = 0; i < allocate.capacity(); i++) {
allocate.put(i * 3);
}
allocate.flip();//读写的状态切花你,就是一个开关。
while (allocate.hasRemaining()) {
System.out.println(allocate.get());
}
}
}
Buffer其实底层就是一个封装了的数组。
直接子类就是没有Boolean类型的
属性
capacity 其实就是数组的大小
limit 存储数据的位置,为了读写切换
position 当前的 下一个位置 因为position是一直变化的,但是limit主要是在切换的时候变化一次
从0 开始,如果读一次,就自动+1
初始化的样子
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
allocate.position(1);/设置其实位置
allocate.limit(2);//下标不会取到limit的值
常用API后序补充
Channel
1,类似于BIO的流
2,可以同时又读和写的功能,流只能是一个功能
3,可以实现异步读写数据
4,可以从buffer中读,也可以向buffer中写。
5,Channel是一个接口:
package bio;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class MyChannel {
public static void main(String[] args) throws Exception {
String str = "hello netty";
FileOutputStream out = new FileOutputStream("d:/a.txt");
FileChannel channel = out.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put(str.getBytes());
buffer.flip();
channel.write(buffer);//写入文件
out.close();
}
}
先要对缓冲区写入
这个类是写入文件,其实一个流只做写入
package bio;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class MyChannel02 {
public static void main(String[] args) throws Exception {
File file = new File("d:/a.txt");
FileInputStream inputStream = new FileInputStream(file);
FileChannel channel = inputStream.getChannel();
ByteBuffer buffer = ByteBuffer.allocate((int)file.length());
channel.read(buffer);//读取文件
System.out.println(new String(buffer.array()));
inputStream.close();
}
}
这个流只做读取。直接读取就行了
文件复制
package bio;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class MyChannel03 {
public static void main(String[] args) throws Exception {
FileInputStream in = new FileInputStream("1.txt");
FileChannel inChannel = in.getChannel();
FileOutputStream out = new FileOutputStream("2.txt");
FileChannel outChannel = out.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(512);
while (true) {
int num = inChannel.read(buffer);
if (num == -1) {
break;
}
buffer.flip();
outChannel.write(buffer);
buffer.clear();//这个很关键,否则position和limit一样无法写入了,会出现死循环
}
in.close();
out.close();
}
}
利用transfer方法,简单复制
package bio;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
public class MyChannel04 {
public static void main(String[] args) throws Exception {
FileInputStream in = new FileInputStream("d:/2.jpg");
FileOutputStream out = new FileOutputStream("d:/美女.jpg");
FileChannel inChannel = in.getChannel();
FileChannel outChannel = out.getChannel();
outChannel.transferFrom(inChannel, 0, inChannel.size());
in.close();
out.close();
}
}
注意
package bio;
import java.nio.ByteBuffer;
public class MyChannel05 {
public static void main(String[] args) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.putInt(10);
buffer.putLong(10L);
buffer.putChar('我');
buffer.putShort((short) 189);
buffer.flip();
// while (buffer.hasRemaining()) {
// System.out.println(buffer.get());//这样会造成解析都是乱的
// }
System.out.println(buffer.getInt());
System.out.println(buffer.getLong());
System.out.println(buffer.getChar());
// System.out.println(buffer.getLong());//Exception in thread "main" java.nio.BufferUnderflowException
System.out.println(buffer.getShort());
}
}
利用nio的新特性做一个本地内存的修改
package bio;
import java.io.FileNotFoundException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
public class MyChannel06 {
public static void main(String[] args) throws Exception {
RandomAccessFile randomAccessFile = new RandomAccessFile("1.txt", "rw");
FileChannel channel = randomAccessFile.getChannel();
MappedByteBuffer map = channel.map(FileChannel.MapMode.READ_WRITE, 0, 5);
map.put(0, (byte) 'a');
map.put(1, (byte) 'b');
randomAccessFile.close();
}
}
这个并没有自己创建的buffer,而是利用channel来帮我们映射了一个本地内存。我们再修改。