缓冲区底层就是数组用于存储不同的数据类型(boolean除外)
//ByteBuffer
//CharBuffer
//ShortBuffer
//IntBuffer
//LongBuffer
//FloatBuffer
//DoubleBuffer
/*
* 上述缓冲区通过allocate方法获取缓冲区
* 缓冲区存取数据两个方法是put和get
* private int mark = -1;
* private int position = 0;缓冲区中正在操作数据的位置
* private int limit;缓冲区中可以操作数据的大小
* private int capacity;表示缓冲区中最大存储量
* */
ByteBuffer allocate = ByteBuffer.allocate(1024);
public static ByteBuffer allocate(int capacity) {
if (capacity < 0)
throw new IllegalArgumentException();
return new HeapByteBuffer(capacity, capacity);
}
HeapByteBuffer(int cap, int lim) { // package-private
super(-1, 0, lim, cap, new byte[cap], 0);
/*
hb = new byte[cap];
offset = 0;
*/
}
Allocate是非直接缓冲区,建立在jvm内存中,中间需要通过copy数据到操作系统内核中再读取
allocatedirect是直接缓冲区,直接建立在啊物理内存中,能够提高效率,零拷贝
相当于在传输时开辟了一块公共的空间,大家都可以访问
传统的bio会阻塞其他用户,如果开辟其他线程服务,大量访问进行时将会拖垮cpu
使用非直接缓冲区完成文件读写
//利用通道完成文件复制
FileInputStream fileInputStream1 = new FileInputStream("1.jpg");
FileOutputStream fileOutputStream = new FileOutputStream("2.jpg");
//获取通道
FileChannel putchannel = fileInputStream1.getChannel();
FileChannel outchannel = fileOutputStream.getChannel();
//获取缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//将通道中的数据存入缓冲区
while(putchannel.read(byteBuffer)!=-1){
//切换到读取数据的模式
byteBuffer.flip();
//将缓冲区中的数据写入通道
outchannel.write(byteBuffer);
//清空缓冲区继续
byteBuffer.clear();
}
outchannel.close();
putchannel.close();
fileInputStream1.close();
fileOutputStream.close();
读写速度慢
直接缓冲区读写数据
FileChannel open = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
FileChannel write = FileChannel.open(Paths.get("2.jpg"),StandardOpenOption.WRITE,StandardOpenOption.READ,StandardOpenOption.CREATE_NEW);
MappedByteBuffer map = open.map(FileChannel.MapMode.READ_ONLY, 0, open.size());
MappedByteBuffer map1 = write.map(FileChannel.MapMode.READ_WRITE, 0, open.size());
byte[] b = new byte[map.limit()];
map.get(b);
map1.put(b);
open.close();
write.close();
//使用直接缓冲区读写数据时不稳定,有时jvm垃圾回收机制不能及时释放资源导致卡内存
//直接缓冲区简单方式:
FileChannel open = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
FileChannel write = FileChannel.open(Paths.get("3.jpg"),StandardOpenOption.WRITE,StandardOpenOption.CREATE);
open.transferTo(0,open.size(),write);
open.close();
write.close();
分散读取与聚集写入
//分散读取,聚集写入
try (RandomAccessFile randomAccessFile = new RandomAccessFile("1.txt", "rw")) {
//获取通道
FileChannel fileChannel = randomAccessFile.getChannel();
//分配缓冲区
ByteBuffer buf1 = ByteBuffer.allocate(1);
ByteBuffer buf2 = ByteBuffer.allocate(1024);
//放入缓冲区数组
ByteBuffer[] b = new ByteBuffer[]{buf1,buf2};
//分散读取
fileChannel.read(b);
for (ByteBuffer byteBuffer:b)
{
byteBuffer.flip();
}
System.out.println(new String(b[0].array(),0,b[0].limit()));
System.out.println("-------------------------------------------");
System.out.println(new String(b[1].array(),0,b[1].limit()));
//聚集写入
RandomAccessFile file2 = new RandomAccessFile("2.txt","rw");
FileChannel channel = file2.getChannel();
channel.write(b);
}
Nio字符集解决乱码
//反射获取对象
Charset charset =Charset.forName("GBK");
//获取编码器
CharsetEncoder charsetEncoder = charset.newEncoder();
//获取解码器
CharsetDecoder charsetDecoder = charset.newDecoder();
//字符非直接缓冲区
CharBuffer charBuffer = CharBuffer.allocate(1024);
charBuffer.put("你好!");
charBuffer.flip();
//编码器编码
ByteBuffer encode = charsetEncoder.encode(charBuffer);
for (int i =0;i<6;i++)
{
System.out.println(encode.get());
}
//解码器解码
encode.flip();
CharBuffer decode = charsetDecoder.decode(encode);
System.out.println(decode.toString());