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