传统IO 面向字节 流(类比水流) NIO: new IO javaNIO核心在于 通道和缓冲区,先获取通道,然后操作缓冲区,对数据进行处理 通道Channel(类比铁路,仅仅用于连接,不能传输数据) 缓冲区Buffer(类比火车,双向) 特点: 面向缓冲区 非阻塞 Buffer 缓冲区 四个核心属性: capacity: 容量,表示缓冲区中最大存储数据的容量,不能改变 limit: 界限,表示缓冲区可以操作数据的大小,limit 后数据不能进行读写 position: 位置,表示缓冲区正在操作的位置 mark:标记,表示记录当前position的位置,可以通过reset()恢复position的位置(没那么重要,只要知道是辅助mark()、reset()操作的就行了) 0<=mark<=position <= limit <= capacity(这个不用记,理解即可) 核心方法: ByteBuffer.allocate();//获取缓冲区 put();//出入数据到缓冲区 get();//获取缓冲区数据 flip();//切换读模式,下面的两个操作不用记,理解即可 limit = position; position = 0; rewind();//重新读 position =0; clear();//清空缓冲区 limit =capacity; position =0; mark();//表示记录当前position的位置,可以通过reset()恢复mark的位置 reset();//恢复到mark位置 非直接缓冲区:通过allocate()方法分配的缓冲区,将缓冲区建立在JVM内存中 直接缓冲区 allocateDirect()方法分配的缓冲区,将缓冲区建立在物理内存中 直接缓冲区可以提升性能,但是不要滥用,建议有明显好处时使用这个,放入直接缓冲区中。 通道Channel:负责缓冲区数据的传输 FileChannel 文件的通道 SocketChannel 网络socket通道 ServerSocketChannel DatagramChannel 获取通道: 很多类中提供getChannel()方法获取通道 本地IO: FileInputStream/FileOutputStream RandomAccessFile 网络IO: Socket ServerSocket DatagramSocket 各个通道类有open()静态方法,获取通道 Files工具类有newByteChannel() 通道的方法: finChannel.read(buf) //把通道的数据写入缓冲区中 foutChannel.write(buf);//把缓冲区的数据读入通道中 channel.read(bufs[]) // 分散读取 将通道的数据分散到多个缓冲区中 channel.write(bufs[]) //聚集写入 将多个缓冲区中的数据聚集到通道中 //通道之间的传输 transferFrom();// 将通道的数据 复制到 另外一个通道中 transferTo();// 从另外的通道获取数据
copy文件:
写法1:
/**
* 利用缓冲区复制文件
*/
public static void copyFile(){
FileInputStream fin = null;
FileOutputStream fout = null;
FileChannel finChannel = null;
FileChannel foutChannel = null;
try {
fin = new FileInputStream("testFile/test.txt");
fout = new FileOutputStream("testFile/test_copy.txt");
finChannel = fin.getChannel();
foutChannel = fout.getChannel();
//缓冲区
ByteBuffer buf = ByteBuffer.allocate(1024);
//将通道中的数据存入缓冲区
while (finChannel.read(buf) != -1){
buf.flip();//切换到读模式
//将缓缓从去的数据写入通道
foutChannel.write(buf);
buf.clear();//缓冲区重置
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭通道和流
if(finChannel != null){
try {
finChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(foutChannel != null){
try {
foutChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fout != null){
try {
fout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fin != null){
try {
fin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
写法2(异常处理已忽略,仅做示例用):
/**
* 利用缓冲区复制文件 直接抛出异常
*/
public static void copyFile_channelCopy() throws Exception {
FileInputStream fin = null;
FileOutputStream fout = null;
FileChannel finChannel = null;
FileChannel foutChannel = null;
fin = new FileInputStream("testFile/test.txt");
fout = new FileOutputStream("testFile/test_channel_copy_2.txt");
finChannel = fin.getChannel();
foutChannel = fout.getChannel();
//直接把通道进行数据传输
// transferTo 和 transferFrom两者选1即可
// finChannel.transferTo(0,finChannel.size(),foutChannel);
foutChannel.transferFrom(finChannel,0,finChannel.size());
//正式写法是需要写在 try-catch-finally 中的,处理仅作为学习
finChannel.close();
foutChannel.close();
fin.close();
fout.close();
}