: 用于原节点与目标节点的连接,类似于传统的流。在Java NIO中负责缓冲区中数据的传输,Channel本身不能直接访问数据,因此需要配合缓冲区buffer进行传输
通道主要实现类:
java.nio.channels.Channel 接口实现:
FileChannel
SocketChannel
ServerSockerChannel
DatagramChannel
获取通道:
- Java 针对支持通道的类提供了getChannel()方法
FileInputStream、FileOutputStream、RandomAccessFile、socker、ServerSocket、DatagramSocket - JDK1.7 中的NIO.2 针对各个通道提供了静态方法open()
- JDK1.7 中的NIO.2 的Files工具类的newByteChannel()方法
利用通道完成文件的复制:
非直接缓冲区
@Test
public void copyFile() {
FileInputStream fis = null;
FileOutputStream fos = null;
FileChannel inChannel = null;
FileChannel outChannel = null;
try {
fis = new FileInputStream(new File("E://a.jpg"));
fos = new FileOutputStream(new File("E://b.jpg"));
inChannel = fis.getChannel();
outChannel = fos.getChannel();
ByteBuffer buf = ByteBuffer.allocate(1024);
while (inChannel.read(buf) != -1) {
buf.flip();
outChannel.write(buf);
buf.clear();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
....close();
}
}
使用直接缓冲区
只有ByteBuffer支持直接缓冲区
@Test
public void copyFileMappedByteBuffer() {
try {
FileChannel inChannel = FileChannel.open(Paths.get("E://a.jpg"), StandardOpenOption.READ);
FileChannel outChannel = FileChannel.open(Paths.get("E://c.jpg"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
//内存映射文件
MappedByteBuffer inMapBuf = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
MappedByteBuffer outMapBuf = outChannel.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size());
//直接对缓冲区进行数据的读写操作
byte dst[] = new byte[inMapBuf.limit()];
inMapBuf.get(dst);
outMapBuf.put(dst);
inChannel.close();
outChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Paths.get()
Paths.get("e","c.jpg")
报错:java.nio.file.NoSuchFileException: e\c.jpg
Paths.get("e:","c.jpg")
正常
映射字节缓冲区的内容可以随时更改,例如,如果此程序或其他程序更改了映射文件的相应区域的内容。这些更改是否发生以及何时发生取决于操作系统,因此未指定。
通道间的数据传输(直接缓冲区):
@Test
public void copyFileTransfer() {
FileChannel inChannel = null;
FileChannel outChannel = null;
try {
inChannel = FileChannel.open(Paths.get("E://a.jpg"), StandardOpenOption.READ);
outChannel = FileChannel.open(Paths.get("e:","e.jpg"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
inChannel.transferTo(0, inChannel.size(), outChannel);
// outChannel.transferFrom(inChannel, 0, inChannel.size());
} catch (IOException e) {
e.printStackTrace();
} finally {
...close();
}
}
分散(scatter)与聚集(Gather)
分散读取(scattering reads):将通道中的数据分散到多个缓冲区中
按照缓冲区的顺序,从Channel中读取的数据依次将buffer填满
聚集写入(gathering writes):将多个缓冲区中的数据聚集到通道中
按照缓冲区的顺序,将buffer中position到limit的数据写入channel
@Test
public void scatter_gather() {
FileChannel inChannel = null;
FileChannel outChannel = null;
RandomAccessFile inf = null;
RandomAccessFile outf = null;
try {
inf = new RandomAccessFile(new File(Paths.get("E://lol.txt").toString()), "rw");
outf = new RandomAccessFile(new File(Paths.get("e:","lol_copy.txt").toString()), "rw");
inChannel = inf.getChannel();
outChannel = outf.getChannel();
ByteBuffer byte1 = ByteBuffer.allocate(100);
ByteBuffer byte2 = ByteBuffer.allocate(1024);
ByteBuffer byteBufferArr[] = new ByteBuffer[]{byte1, byte2};
inChannel.read(byteBufferArr);
for(ByteBuffer b : byteBufferArr) {
b.flip();
}
System.out.println(new String(byteBufferArr[0].array(), 0, byteBufferArr[0].limit()));
System.out.println(new String(byteBufferArr[1].array(), 0, byteBufferArr[1].limit()));
outChannel.write(byteBufferArr);
} catch (IOException e) {
e.printStackTrace();
} finally {
...close();
}
}
字符集charset
编码:字符串->字节数组
解码:字节数组->字符串
@Test
public void charset() {
System.out.println(Charset.availableCharsets());
Charset gbk = Charset.forName("GBK");
//获取解码器
CharsetDecoder gbkDecoder = gbk.newDecoder();
//获取编码器
CharsetEncoder gbkEncoder = gbk.newEncoder();
CharBuffer charBuffer = CharBuffer.allocate(1024);
charBuffer.put("王腾shippuden");
charBuffer.flip();
try {
ByteBuffer encode = gbkEncoder.encode(charBuffer);
for (int i = 0; i < 12; i++) {
System.out.println(encode.get());
}
encode.flip();
CharBuffer decode = gbkDecoder.decode(encode);
System.out.println(decode.toString());
} catch (CharacterCodingException e) {
e.printStackTrace();
}
}