1.为什么要用NIO

NIO 的创建目的是为了让 Java 程序员可以实现高速 I/O 而无需编写自定义的本机代码。NIO 将最耗时的 I/O 操作(即填充和提取缓冲区)转移回操作系统,因而可以极大地提高速度。 原来的 I/O 库(在 java.io.*中) 与 NIO 最重要的区别是数据打包和传输的方式。正如前面提到的,原来的 I/O 以流的方式处理数据,而 NIO 以块的方式处理数据。

2.NIO核心对象:缓冲区

什么是缓冲区? Buffer 是一个对象, 它包含一些要写入或者刚读出的数据。 在 NIO 中加入 Buffer 对象,体现了新库与原 I/O 的一个重要区别。在面向流的 I/O 中,您将数据直接写入或者将数据直接读到 Stream 对象中。 在 NIO 库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的。在写入数据时,它是写入到缓冲区中的。任何时候访问 NIO 中的数据,您都是将它放到缓冲区中。

最常用的缓冲区类型是 ByteBuffer。一个 ByteBuffer 可以在其底层字节数组上进行 get/set 操作(即字节的获取和设置)。

3.NIO核心对象:通道

什么是通道? Channel是一个对象,可以通过它读取和写入数据。拿 NIO 与原来的 I/O 做个比较,通道就像是流。 正如前面提到的,所有数据都通过 Buffer 对象来处理。您永远不会将字节直接写入通道中,相反,您是将数据写入包含一个或者多个字节的缓冲区。同样,您不会直接从通道中读取字节,而是将数据从通道读入缓冲区,再从缓冲区获取这个字节。

通道类型: 通道与流的不同之处在于通道是双向的。而流只是在一个方向上移动(一个流必须是 InputStream 或者 OutputStream 的子类), 而 通道 可以用于读、写或者同时用于读写。

实例:

NIO读文件

@Test
public void read() throws Exception {
//第一步是获取通道,我们从FileInpustream获取通道
FileInputStream fin = new FileInputStream("C:\\Users\\Administrator\\Desktop\\Test.txt");
FileChannel channel = fin.getChannel();
//下一步是创建缓冲区
ByteBuffer buf = ByteBuffer.allocate(1024); StringBuilder sb = new StringBuilder(); //通过通道读取文件内容到缓冲区,未读到文件最后就一直读取
while ((channel.read(buf)) != -1) {
//调用flip之后,读到指针到缓存头部,并且设置最多只能读出之前写入的数据长度(而不是整个缓存容量的大小)
buf.flip();
//循环判断缓冲区是否还有可用数据 while (buf.hasRemaining()) {
char b = (char) buf.get(); sb.append(b);
//读取缓冲区内容,转换成CHAR型 }
System.out.println(String.valueOf(sb));
//compact():只会清除已经读过的数据 任何未读的数据都被移到缓冲区的其实出
//新写入的数据将放到缓冲区未读数据的后面
buf.compact(); } }

NIO写文件

@Test
public void write() throws IOException {
String mess[] = {"09","099","665","655","355"};
//创建文件字节输出流
FileOutputStream fout = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\Test2.txt");
//从字节流中获取通道
FileChannel channel = fout.getChannel();
//创建缓冲区对象 (allocate分配)
ByteBuffer buffer = ByteBuffer.allocate(1024); //通过管道往缓冲区写数据
for (int i = 0; i <mess.length ; i++) {
buffer.put(mess[i].getBytes());
} //改变缓冲区指针
buffer.flip(); //把缓冲区内容写入到通道
channel.write(buffer); //紧凑
buffer.compact(); //关流
fout.close(); }

NIO读写结合

@Test
public void Nio() throws IOException {
//创建字节输入流
FileInputStream fin = new FileInputStream("C:\\Users\\Administrator\\Desktop\\Test.txt"); //创建字节输出流
FileOutputStream fout = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\Test3.txt"); //创建输入通道
FileChannel finChannel = fin.getChannel();
//创建输出通道
FileChannel foutChannel = fout.getChannel(); //创建Nio的缓冲流
ByteBuffer buffer = ByteBuffer.allocate(1024); //循环
while (true) {
//clear方法重置缓冲区,使他可以接受读入的数据()position
buffer.clear(); //从输入通道读取内容到缓冲区
int r = finChannel.read(buffer);
//如果读取到文件的结尾 返回的结果为-1
if (r == -1){
break;
}
//flip()方法可以一步步读取缓冲区的内容
buffer.flip(); foutChannel.write(buffer); }
//关流
fin.close();
fout.close();
}

最新文章

  1. SQL SERVER 2008 获取表字段的类型
  2. union内嵌struct用法
  3. 使用VirtualBox进行端口转发 连接数据库
  4. 从零开始学ios开发(十五):Navigation Controllers and Table Views(中)
  5. 【转】如图,win7登陆界面,键盘失灵,没办法登陆。求解!如何在这个界面打开个鼠标可以点的软键盘
  6. OC之JSON数据解析
  7. 在浏览器中打不开Oracle 11gR2的企业管理器页面
  8. mac下 配置 Apache Php Mysql
  9. MyBatis源码解读(1)——SqlSessionFactory
  10. beautifulsoup爬取糗事百科
  11. Android JNI 学习(七):Accessing Fields Api
  12. 使用 vagrant新建Linux虚拟机
  13. 一些调格式的经验 &amp; 插入图注和尾注
  14. 通过使用CSS字体阴影效果解决hover图片时显示文字看不清的问题
  15. 用optional取代null
  16. Android-Drawable(三)
  17. 9th 学习博客:使用Codebloks实现C++的图形化界面
  18. Android Studio 2.2 Record Espresso Test
  19. \G,sql中select 如果太长,可以在后面放\G,竖行显示~~~~
  20. Q678 有效的括号字符串

热门文章

  1. arean.c
  2. handsontable-developer guide-cell editor
  3. acm.njupt 1001-1026 简单题
  4. unity shader序列帧动画代码,顺便吐槽一下unity shader系统
  5. ORACLE PATCH 版本的查询 PL/SQL
  6. [转载]MVC、MVP以及Model2(上)
  7. 遇到了IE10不能登录的问题,很早就有解决方案了
  8. 解决IE8不支持console
  9. 对java位运算之异或运算的一点记录
  10. 升级到Sharepoint 2013后页面打开速度慢