课件代码:https://gitee.com/flymini/codes01/tree/master/example_/com-learn-nio02
****
**1. 传统的IO读写文件**
```java
public class IOUtils {
/**
* 文件拷贝
*/
public final static void traditionalCopy(String sourcePath, String destPath) throws IOException {
File source = new File(sourcePath);
File dest = new File(destPath);
if (!dest.exists()) {
dest.createNewFile();
}
FileInputStream fis = new FileInputStream(source);
FileOutputStream fos = new FileOutputStream(dest);
byte[] buf = new byte[1024];
int len = 0;
while ((len = fis.read(buf)) != -1) {
fos.write(buf);
}
fis.close();
fos.close();
}
}
```
**2. NIO读写文件**
```java
public class NIOFileUtils {
/**
* 文件拷贝
*/
public final static void nioCopy(String sourcePath, String destPath, int allocate) throws IOException {
ByteBuffer byteBuffer = ByteBuffer.allocate(allocate);
FileInputStream fis = new FileInputStream(sourcePath);
FileOutputStream fos = new FileOutputStream(destPath);
FileChannel inChannel = fis.getChannel();
FileChannel outChannel = fos.getChannel();
int length = inChannel.read(byteBuffer);
while (length != -1) {
byteBuffer.flip(); // 读取模式转写入模式
outChannel.write(byteBuffer);
byteBuffer.clear(); // 情况缓存,等待下次写入
length = inChannel.read(byteBuffer);
}
fos.close();
outChannel.close();
fis.close();
inChannel.close();
}
/**
* 文件拷贝
*/
public final static void nioCopy(String sourcePath, String destPath) {
File source = new File(sourcePath);
File dest = new File(destPath);
FileInputStream fis = null;
FileOutputStream fos = null;
FileChannel inChannel = null;
FileChannel outChannel = null;
try {
fis = new FileInputStream(source);
fos = new FileOutputStream(dest);
inChannel = fis.getChannel();
outChannel = fos.getChannel();
int position = 0;
long size = inChannel.size();
while (size > 0) {
//数据超过2G,transferTo方法不能做到一次性转移,所以这里弄个循环
long count = inChannel.transferTo(0, inChannel.size() * 2, outChannel);
if (count > 0) {
position += count;
size -= count;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fis.close();
fos.close();
inChannel.close();
outChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 读文件
*/
public final static void read(String file, int allocate) throws IOException {
//以只读模式打开文件
RandomAccessFile accessFile = new RandomAccessFile(file, "r");
FileChannel fileChannel = accessFile.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(allocate);
CharBuffer charBuffer = CharBuffer.allocate(allocate);
Charset charset = Charset.forName("UTF-8");
CharsetDecoder decoder = charset.newDecoder();
int length = fileChannel.read(byteBuffer);
while (length != -1) {
//读模式转换为写模式
byteBuffer.flip();
decoder.decode(byteBuffer, charBuffer, true);
//写模式转换为读模式
System.out.println(charBuffer.toString());
//清空缓存
byteBuffer.clear();
charBuffer.clear();
length = fileChannel.read(byteBuffer);
}
fileChannel.close();
if (accessFile != null) {
accessFile.close();
}
}
/**
* 写文件
*/
public final static void write(String context, String file, int allocate) throws IOException {
//rws:每当进行写操作,同步的刷新到磁盘,刷新内容和元数据
RandomAccessFile accessFile = new RandomAccessFile(file, "rws");
FileChannel fileChannel = accessFile.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(allocate);
//往缓冲区推送数据
byteBuffer.put(context == null ? "".getBytes() : context.getBytes());
//读模式转换为写模式
byteBuffer.flip();
int length = fileChannel.write(byteBuffer);
fileChannel.close();
if (accessFile != null) {
accessFile.close();
}
}
}
```
**3. 比较两种方式读写文件的性能**
```java
public class MainTest {
//CentOS-7.0-1406-x86_64-DVD.iso 文件大约为 4G
String sourcePath = "E:\\CentOS-7.0-1406-x86_64-DVD.iso";
String destPath = "E:\\CentOS-7.0-1406-x86_64-DVD-dest.iso";
@Test
public void testTraditionalCopy() throws IOException {
long start = System.currentTimeMillis();
IOUtils.traditionalCopy(sourcePath, destPath);
long end = System.currentTimeMillis();
System.out.println("消耗时间:" + (end - start));
//消耗时间:220100
}
@Test
public void testNioCopy1() throws IOException {
long start = System.currentTimeMillis();
NIOFileUtils.nioCopy(sourcePath, destPath, 1024);
long end = System.currentTimeMillis();
System.out.println("消耗时间:" + (end - start));
//消耗时间:37186
}
@Test
public void testNioCopy2() throws IOException {
long start = System.currentTimeMillis();
NIOFileUtils.nioCopy(sourcePath, destPath);
long end = System.currentTimeMillis();
System.out.println("消耗时间:" + (end - start));
//消耗时间:71007
}
}
```
很明显,当文件较大时,NIO的优势就越能够体现出来。
- 网络通信
- 网络协议
- 端口和套接字
- TCP网络程序
- UDP网络程序
- 多线程聊天室
- 多线程
- 线程相关概念
- 线程实现方式
- 中断线程
- 线程生命周期
- 线程优先级
- 优先级规则
- 案例演示
- 线程同步机制
- 线程同步机制
- synchronized关键字
- ReentrantLock类
- Condition类
- 监视器概念
- volatile关键字
- final变量
- 死锁
- 线程局部变量
- 读/写锁
- 原子类
- 阻塞队列
- 工作规则
- 案例演示
- 常用阻塞队列
- 线程安全集合
- 高效的映射/集/队列
- 并发集视图
- 写数组的拷贝
- Arrays类的并行数组算法
- 同步包装器
- Callable与Future
- 执行器
- 线程池
- 预定执行
- 控制任务组
- Fork-Join框架
- 同步器
- 同步器
- 信号量
- CountDownLatch类
- CyclicBarrier类
- Exchanger类
- SynchronousQueue类
- 线程与Swing
- Swing与线程问题
- 两个原则
- Swing工作线程
- 单一线程规则
- 文件IO
- File类
- 文件输入输出
- ZIP压缩文件
- 集合
- 集合框架
- 集合接口
- 集合实现类
- 线程安全集合
- 集合算法
- 迭代器
- 集合排序
- JDBC
- JDBC是什么
- JDBC-ODBC桥
- JDBC驱动程序类型
- JDBC常用类与接口
- 数据库操作
- 连接数据库
- 增/删/改/查/预处理
- 事务
- 批处理
- commons-dbutils工具
- 安全问题
- Jedis
- 使用Jedis操作Redis数据库
- JSON转换
- 使用连接池
- 案例
- 单例破坏
- 单例定义
- 单例实现方式
- 懒汉式实现单例
- 饿汉式实现单例
- 单例破坏
- 类的单例破坏
- 枚举的单例破坏
- 克隆
- 克隆是什么
- 浅克隆
- 深克隆
- 注解
- 注解是什么
- 三大注解
- 内置注解
- 元注解
- 自定义注解
- NIO
- 相关概念
- BIO/NIO/AIO
- 多线程编程
- 线程同步
- 线程通信
- NIO
- NIO三大核心组件
- NIO网络编程
- NIO文件读写
- AIO
- Java8新特性
- Lambda表达式
- 方法引用
- 函数式接口
- 默认方法
- 什么是默认方法
- 默认方法语法格式
- 多个同名的默认方法问题
- 静态默认方法
- 默认方法实例
- Stream
- Stream是什么
- Stream示例
- Optional容器
- 新的日期时间API
- Base64
- SPI
- SPI是什么
- SPI与API的区别
- 常见场景
- 使用SPI需遵循的约定
- SPI使用步骤