主要就是两个概念:Channel Buffer
解释
通道
:给我的感觉就像c的fd句柄一样.buffer
:就是一个存储文件的缓冲区,这里值得注意的是它是有模式的,不是以前学习- c的那种buff就是一个简单的buffer
- 选择器(selectors):一个选择器可以监听多个Channel,这个可以回去看看书上的Epoll
- Scannter 一个Channel可以读取数据到多个Buffer当然,buffer是作为buffer的形式作为参数
nio是非阻塞的io
channel与Buffer实现
channel实现 | 解释 |
---|---|
FileChannel | 文件通道 |
datagramChannel | udp通道 |
SocketChannel | tcp通道 |
serverSocketChannel | 可以监听新进来的tcp连接,每个新连接创建一个SocketChannel |
buffer解释
* ByteBuffer
* CharBuffer
* DoubleBuffer
* FloatBuffer
* IntBuffer
* LongBuffer
* ShortBuffer
下面是一个简单的实例路线如下
- 先有个channel->b.txt的通道
- 再有个buffer[]
- channel读取数据到buffer
- channel->a.txt的通道
- buffer切换模式从写切换到读模式,不然获取写入到文件会一个数据也写不进去
把buffer写到channel->a.txt
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.Selector;
public class Gatter {
public static void main(String[] argv){
RandomAccessFile aFile = null;
try {
aFile = new RandomAccessFile("a.txt", "rw");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
FileChannel channel = aFile.getChannel();
ByteBuffer[] buffArray = null;
try {
buffArray = getBuffArray();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//这里成功输出
printByteArray(buffArray[0].array());
System.out.println("---------------------------");
System.out.println(buffArray[0].array().length);
for(ByteBuffer byteBuffer : buffArray){
byteBuffer.flip(); //Buffer有读和写两种模式 之前处于写模式
//这里如果不做模式转换会出现写失败的情况
}
try {
System.out.println(channel.write(buffArray));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(channel != null){
try {
channel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static ByteBuffer[] getBuffArray() throws IOException{
RandomAccessFile randomAccessFile = null;
try {
randomAccessFile = new RandomAccessFile("b.txt", "rw");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//接口不能作为句柄 下面的代码就是Scantter的核心理念 居然不是语法而是类似于技巧
FileChannel channel = randomAccessFile.getChannel();
ByteBuffer buffer01 = ByteBuffer.allocate(1024);
ByteBuffer buffer02 = ByteBuffer.allocate(1024);
ByteBuffer[] buffArray = {buffer01 , buffer02};
try {
channel.read(buffArray);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//printByteArray(buffArray[1].array());
if(channel != null){
channel.close();
}
return buffArray ;
}
private static void printByteArray(byte[] arr){
try {
System.out.println(new String(arr , "utf-8"));
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
上面的例子也有更加简单的实现通过一个通道的transferFrom的方法来实现
函数说明:就是把参数里的channel的数据对拷到此channel中,当然这里只是简单测试了filechannel的
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class transferFrom {
public static void main(String[] args) {
// TODO Auto-generated method stub
RandomAccessFile randomAccessFile = null;
try {
randomAccessFile = new RandomAccessFile("a.txt", "rw");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
FileChannel channel = randomAccessFile.getChannel();
FileChannel toFileChannel = null;
try {
toFileChannel = getChannel();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
channel.transferFrom(toFileChannel, 0, toFileChannel.size());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(toFileChannel != null){
try {
toFileChannel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(channel != null){
try {
channel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static FileChannel getChannel() throws IOException{
RandomAccessFile randomAccessFile = null;
try {
randomAccessFile = new RandomAccessFile("b.txt", "rw");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//接口不能作为句柄 下面的代码就是Scantter的核心理念 居然不是语法而是类似于技巧
FileChannel channel = randomAccessFile.getChannel();
return channel ;
}
}