Java NIO(一)-Channel和Buffer
2018-06-11 本文已影响0人
行动的侏儒
- Channel
Channel类似于流,但和流不同,流是单向的只能读或写,Channel是既可以读又可以写。Channel常见的实现类有FileChannel、DatagramChannel、SocketChannel、ServerSocketChannel。BIO中的FileInputStream、FileOutputStream和RandomAccessFile能通过getChannel方法得到FileChannel对象 - Buffer
Buffer是唯一能与Channel交互的对象,它的常见实现有ByteBuffer、ShortBuffer、IntBuffer、LongBuffer、DoubleBuffer、FloatBuffer、CharBuffer。Buffer有四个属性position、limit、capacity和mark,Buffer初始化的时候需要指定容量capacity,Buffer它的底层实现是一个数组,如下图,以ByteBuffer为例,position表示数组中下一个要读或写的位置,当向Buffer写完后(不一定写满),调用flip()方法,将Buffer的读写模式翻转,limit赋值为position,position赋值为0。mark是标记位置,可以通过reset()方法,将position值变为mark值。
public abstract class ByteBuffer
extends Buffer
implements Comparable<ByteBuffer>
{
final byte[] hb; // Non-null only for heap buffers
final int offset;
boolean isReadOnly; // Valid only for heap buffers
}
直接看看ByteBuffer的简单使用:
public class ByteBufferTest {
public static void main(String[] args) {
try {
FileInputStream is = new FileInputStream("/home/reda/Documents/test/1.txt");
FileOutputStream fos = new FileOutputStream("/home/reda/Documents/test/1.txt");
FileOutputStream os = new FileOutputStream("/home/reda/Documents/test/2.txt");
FileChannel inChannel = is.getChannel();
FileChannel fosChannel = fos.getChannel();
FileChannel outChannel = os.getChannel();
//特殊情况,直接在channel传输
// inChannel.transferTo(0,inChannel.size(),outChannel);
// outChannel.transferFrom(inChannel,0,inChannel.size());
ByteBuffer buffer = ByteBuffer.allocate(16);
//写入内容
fosChannel.write(ByteBuffer.wrap("1234QAQ".getBytes("UTF-8")));
// while(inChannel.read(buffer) != -1) {
// buffer.flip();
// outChannel.write(buffer);
// //必须clear不然除了第一次,后面将读不进内容到Buffer
// buffer.clear();
// }
buffer.clear();
fosChannel.close();
inChannel.read(buffer);
buffer.flip();
//将positon的位置标记在起始位置,将ByteBuffer中每个字节转为字符
buffer.mark();
while (buffer.hasRemaining()) {
System.out.print((char)buffer.get());
}
System.out.println();
//将positon的位置重置
buffer.reset();
CharBuffer charBuffer = buffer.asCharBuffer();
//打印乱码,ByteBuffer直接转成CharBuffer不行
System.out.println(charBuffer.toString());
//将ByteBuffer解码成utf8后,则能重新正确打印
CharBuffer charBuffer2 = Charset.forName("UTF-8").decode(buffer);
System.out.println(charBuffer2.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
ByteBuffer类有方法能转换成其他类型的Buffer
Buffer类型转换
public class BufferTest {
public static void main(String[] args) {
ByteBuffer buffer = ByteBuffer.wrap(new byte[]{0,0,0,0,0,0,0,'a'});
//byteBUffer result:0 0 0 0 0 0 0 97
while (buffer.hasRemaining())
System.out.print(buffer.get() + " ");
//CharBuffer result: a
CharBuffer charBuffer = ((ByteBuffer)buffer.rewind()).asCharBuffer();
while (charBuffer.hasRemaining())
System.out.print(charBuffer.get() + " ");
//FloatBuffer result: 0.0 1.36E-43
FloatBuffer floatBuffer = ((ByteBuffer)buffer.rewind()).asFloatBuffer();
while (floatBuffer.hasRemaining())
System.out.print(floatBuffer.get() + " ");
//IntBuffer result:0 97
IntBuffer intBuffer = ((ByteBuffer)buffer.rewind()).asIntBuffer();
while (intBuffer.hasRemaining())
System.out.print(intBuffer.get() + " ");
//ShortBuffer result:0 0 0 97
ShortBuffer shortBuffer = ((ByteBuffer)buffer.rewind()).asShortBuffer();
while (shortBuffer.hasRemaining())
System.out.print(shortBuffer.get() + " ");
//LongBuffer result:97
LongBuffer longBuffer = ((ByteBuffer)buffer.rewind()).asLongBuffer();
while (longBuffer.hasRemaining())
System.out.print(longBuffer.get() + " ");
//DoubleBuffer result:4.8E-322
DoubleBuffer doubleBuffer = ((ByteBuffer)buffer.rewind()).asDoubleBuffer();
while (doubleBuffer.hasRemaining())
System.out.print(doubleBuffer.get() + " ");
}
}
- 一字节:byte boolean
- 二字节: char short
- 四字节:int float
- 八字节:long double
ByteBuffer包装了一个8字节的数组,byteBuffer每个值有一个字节所以有8个值,同理char、short4个值(char的前三个值为空,没显示),int、float2个值,long和double一个值。