`
guibin
  • 浏览: 363848 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java NIO 入门(三)从理论到实践:使用NIO读写

    博客分类:
  • Java
阅读更多
Java NIO 入门(三)从理论到实践:使用NIO读写
guibin.beijing@gmail.com

概述
读和写是最基础的IO处理。从Channel中读是非常简单的,我们只要创建一个Buffer,然后要求Channel往Buffer中读数据。写也很简单,也需要创建一个Buffer,把要写的数据填充到Buffer中,然后要求Channel把Buffer中的数据写出去。

在这节中,我们学习使用JAVA程序来读写数据,顺便浏览一下NIO的主要组件(Buffer,Channel以及相关的方法)并且看看他们在读写数据时如何交互,在后面的章节中我们将依次查看每个组件的细节。

从文件中读数据
在第一个练习中,我们首先从文件中读取一些数据。如果使用老的IO,只需要简单的创建FileInputStream,然后从中读取数据。在NIO中,事情变得有些不同了,首先需要从FileInputStream中获取Channel对象,然后使用这个Channel去读文件。

在NIO系统中任何时刻执行一个读操作时,都要从Channel中读,但不是直接从Channel中读。由于所有的数据都需要通过Buffer承载,所以需首先从Channel中把数据读进Buffer。

因此,从文件中读数据一共有三步:
  • 从FileInputStream中获取Channel
  • 创建Buffer
  • 从Channel中把数据读入Buffer

下面我们仔细看看具体时如何工作的。

三步简单的工作
第一步获取Channel。从FileInputStream中获取Channel。
FileInputStream fin = new FileInputStream( "readandshow.txt" ); 
FileChannel fc = fin.getChannel();

第二步创建Buffer
ByteBuffer buffer = ByteBuffer.allocate( 1024 );

最后一步,将文件内容通过Channel读入Buffer中
fc.read( buffer );

你一定发现,在这里,并没有告诉Channel把多少内容读进Buffer。在每个Buffer中都有一套完整的内部计数系统来跟踪已经读了多少数据了,Buffer中还剩多少空间。关于Buffer的计数系统在随后的“Buffer内部原理”中讲解。

写文件
使用NIO写文件和读文件非常类似。我们还是从FileOutputStream中获取Channel。
FileOutputStream fout = new FileOutputStream( "writesomebytes.txt" );
FileChannel fc = fout.getChannel();

下一步还是创建Buffer并且把数据放到Buffer中。在这种情况下数据将从一个叫做message的数组中取出,这个数组中包含了字符串ASCII码的字节。(The buffer.flip() 和 buffer.put()在后面讲解)
ByteBuffer buffer = ByteBuffer.allocate( 1024 );
for (int i=0; i<message.length; ++i) { 
  buffer.put( message[i] );
} 
buffer.flip();

最后一步就是把Buffer写出去。
fc.write( buffer );


再次注意,我们没有必要告诉Channel总共要写多少数据,Buffer的内部计数系统会跟踪已经写了多少数据了,还剩多少空间可以使用。

边读边写
下面看看当我们把读和写结合起来会发生什么。这个练习程序的名称叫CopyFile.java,用来从一个文件拷贝全部数据到另一个文件。Copy.java包含了三个基本的操作:
  • 首先创建Buffer
  • 然后从源文件把数据读入Buffer
  • 最后把Buffer写入目的文件

程序重复的进行读写、读写,直到文件读完。

CopyFile程序能够看到如何检查程序的状态,以及如何使用clear(),flip()方法重置Buffer,如何读数据从一个Channel到另一个Channel。

运行CopyFile例子
因为Buffer跟踪了自己的内部数据,因此CopyFile程序的内部循环非常简单,如下:
fcin.read( buffer ); 
fcout.write( buffer );

首先数据从输入Channel中读入Buffer,然后把数据写出到输出Channel中。因为输入和输出分别对应于两个文件,因此是两个Channel。

检查读文件的状态
下一步,当我们在拷贝时需要检查读文件的状态。当没有数据可读时即执行完毕,这个状态可以通过read()方法返回-1来判断,如下:
int r = fcin.read( buffer );
if (r==-1) { 
  break;
}


重置Buffer
最后,在从Channel将数据读入Buffer前调用clear()方法,相似的,在将Buffer写入输出Channel之前调用flip()方法。
buffer.clear(); 
int r = fcin.read( buffer );

if (r==-1) { 
  break;
}

buffer.flip(); 
fcout.write( buffer );


clear()方法重置了Buffer,使其准备好能够将读入的数据放入Buffer中。flip()方法使得Buffer准备好把Buffer中的数据写入Channel。

本文参考自http://www.cs.brown.edu/courses/cs161/papers/j-nio-ltr.pdf


0
2
分享到:
评论

相关推荐

    Java SE实践教程 pdf格式电子书 下载(四) 更新

    Java SE实践教程 pdf格式电子书 下载(三) 更新 http://download.csdn.net/source/2824042 Java SE实践教程 pdf格式电子书 下载(四) 更新 http://download.csdn.net/source/2824046 内容简介:此书结合具体实例...

    mycat从入门到跑路

    Mycat从入门到精通视频教程目录介绍: 第1课 Mycat前世今生 Mycat的历史、背后的团队、发展现状、RoadMap等 第2课 Mycat原理与入门 Mycat的原理、主要功能、配置和使用入门 第3课 Mycat故障排查指南 常见问题 日志...

    JAVA上百实例源码以及开源项目

    通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥,通常应对私钥加密后再保存、如何从...

    JAVA上百实例源码以及开源项目源代码

    通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥,通常应对私钥加密后再保存、如何从...

    java开源包8

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包11

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包6

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包4

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包9

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包101

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包5

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包10

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    疯狂JAVA讲义

    学生提问:当我们使用编译C程序时,不仅需要指定存放目标文件的位置,也需要指定目标文件的文件名,这里使用javac编译Java程序时怎么不需要指定目标文件的文件名呢? 13 1.5.3 运行Java程序 14 1.5.4 根据...

    java开源包1

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包3

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包2

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包7

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    Java资源包01

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    spring-boot示例项目

    该项目包含helloworld(快速入门)、web(ssh项目快速搭建)、aop(切面编程)、data-redis(redis缓存)、quartz(集群任务实现)、shiro(权限管理)、oauth2(四种认证模式)、shign(接口参数防篡改重放)、encoder(用户...

Global site tag (gtag.js) - Google Analytics