1.NIO(即New IO)概念
JDK1.4版本开始,JDK提供了新的IO操作API, NIO提供多路(non-blocking) 非阻塞式的高伸缩性网络I/O,从而提高了效率,NIO主要有三大核心组件:Channel、Buffer和Selector。
2.Buffer类
Buffer是一个抽象类,Buffer类型变量对应的对象代表一块缓冲区,ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer和ShortBuffer类都是Buffer抽象类的子类,其中ByteBuffer最常用。
3.ByteBuffer常用方法:
① ByteBuffer allocate(int capacity【一个int类型的数据】):分配一个新的字节缓冲区。
静态方法,直接用类名调用,定义方法如下:
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
此时 byteBuffer 表示一块缓冲区
②返回int类型
capacity() :返回此缓冲区的容量。
③byteBuffer. put(byte b):将字节类型数据写入当前位置的缓冲区,然后当前位置+1,位置从0开始。
④返回int类型
position():返回缓冲区当前位置,返回的int数据也是从0开始计算的
package sun;
import java.nio.ByteBuffer;
public class Test {
public static void main(String[] args) {
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
byte a =1;
byte b=2;
byteBuffer.put(a);
byteBuffer.put(b);
int size = byteBuffer.capacity();
System.out.println(size);
System.out.println(byteBuffer.position());
}
}
运行结果:
⑤Buffer flip() :翻转缓冲区,将position置零。调用方式:byteBuffer.flip();
package sun;
import java.nio.ByteBuffer;
public class Test {
public static void main(String[] args) {
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
byte a = 1;
byte b = 2;
byteBuffer.put(a);
byteBuffer.put(b);
System.out.println(byteBuffer.position());
byteBuffer.flip();
System.out.println(byteBuffer.position());
}
}
运行结果
⑥byte get()读取缓冲区当前位置的字节,然后当前位置+1,也是从0开始计算的。
package sun;
import java.nio.ByteBuffer;
public class Test {
public static void main(String[] args) {
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
byte a = 1;
byte b = 2;
byteBuffer.put(a);
byteBuffer.put(b);
System.out.println(byteBuffer.get());
//如果没有参数值,就是返回当前位置的数值,因为put方法向后加一,所以还没有给第三个元素赋值,结果为0
System.out.println(byteBuffer.get(0));
System.out.println(byteBuffer.get(1));
}
}
运行结果
⑦Buffer clear():清除缓冲区,位置归零。与byteBuffer.flip();用法相似,有覆盖的意思。
⑧byte[] array() :将ByteBuffer类型的数据转为byte数组。
package sun;
import java.nio.ByteBuffer;
public class Test {
public static void main(String[] args) {
ByteBuffer byteBuffer = ByteBuffer.allocate(4);
byte[] car = byteBuffer.array();
for (byte b : car) {
System.out.println(b);
}
}
}
运行结果
⑨boolean hasRemaining():判断缓冲区“指针”指向的地方是否还有内存。
package sun;
import java.nio.ByteBuffer;
public class Test {
public static void main(String[] args) {
ByteBuffer byteBuffer = ByteBuffer.allocate(3);
System.out.println(byteBuffer.get());//position 0
System.out.println(byteBuffer.hasRemaining());
System.out.println(byteBuffer.get());//position 1
System.out.println(byteBuffer.hasRemaining());
System.out.println(byteBuffer.get());//position 2
System.out.println(byteBuffer.hasRemaining());
}
}
4.Channel是一个接口,该接口类型变量指向的对象代表一个数据传输通道,Channel对象是面向缓冲区的:文件中的数据总是从通道读取到缓冲区(Buffer类型对象),或从缓冲区(Buffer类型对象)写入到通道中再到新的文件中。
FileChannel:从文件中读写数据。
只能通过调用FileInputStream和FileOutputStream类中getChannel方法获取FileChannel对象,FileChannel类常用方法如下:
①返回int类型
read(ByteBuffer dst):从通道的当前文件位置开始将数据读取到缓冲区,然后以实际读取的字节数更新文件位置;返回实际读取的字节数,如果已达到通道末尾, 则返回-1
②返回void类型
close():关闭通道。
③返回int类型
write(ByteBuffer src):从通道的当前文件位置开始将缓冲区中数据写入通道,然后文件位置用实际写入的字节数更新。
package sun;
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class Test {
public static void main(String[] args) {
try {
FileInputStream fileInputStream = new FileInputStream("D:\\1.txt");
FileChannel fileChannel =fileInputStream.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
try {
while((fileChannel.read(byteBuffer))!=-1) {
String result = new String(byteBuffer.array(),0,byteBuffer.position()); //String类的构造方法
System.out.println(result);
byteBuffer.clear();
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
但是这个文件的设置需要编码一样,eclipse的编码是UTF-8所以,要求这个文本文档的编码的也是UTF-8。
实现用管道和缓冲区复制文件。
package sun;
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class Test {
public static void main(String[] args) {
try {
FileInputStream fileInputStream = new FileInputStream("D:\\1.txt");
FileChannel inputfileChannel = fileInputStream.getChannel();
FileOutputStream fileOutputStream = new FileOutputStream("D:\\6.txt");
FileChannel outputfileChannel = fileOutputStream.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
while((inputfileChannel.read(byteBuffer))!=-1) { //从通道的当前文件位置开始将数据读取到缓冲区
byteBuffer.flip();
outputfileChannel.write(byteBuffer); //开始将缓冲区中数据写入通道
byteBuffer.clear();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}