服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

merlin 的魔力:merlin 的新 i/o 缓冲区的输入和输出


  merlin 的魔力:merlin 的新 i/o 缓冲区的输入和输出
  
  作者:
  
  
  
  merlin 的魔力:
  
  merlin 的新 i/o 缓冲区的输入和输出
  
  英文原文
  
  内容:
  
  缓冲区基础
  
  缓冲区类型
  
  直接 vs. 间接
  
  内存映射文件
  
  结束语
  
  参考资料
  
  关于作者
  
  对本文的评价
  
  相关内容:
  
  merlin 给 java 平台带来了非阻塞 i/o
  
  working xml: wrestling with java nio
  
  t彻底转变流,第 2 部分:优化 java 内部 i/o
  
  merlin的魔力
  
  developerworks toolbox subscription
  
  在 java 专区还有:
  
  工具与产品
  
  代码与组件
  
  所有文章
  
  实用技巧
  
  了解如何操作 j2se 1.4 的新 i/o 包
  
  级别:初级
  
  john zukowski
  
  jaz@zukowski.net
  
  总裁,jz ventures 公司
  
  2003 年 6 月
  
  merlin 的魔力
  
  中,常驻 java 编程专家 john zukowski 展示了如何操作那些数据缓冲区来执行如读/写原语这样的任务以及如何使用内存映射文件。在以后的文章里,他将把这里所提到的概念扩展到套接字通道的使用。
  
  java 2 平台标准版(java 2 platform standard edition,j2se)1.4 对 java 平台的 i/o 处理能力做了大量更改。它不仅用流到流的链接方式继续支持以前
  
  j2se 发行版的基于流的 i/o 操作,而且 merlin 还添加了新的功能 ― 称之为新 i/o
  
  类(nio),现在这些类位于
  
  java.nio
  
  包中。
  
  i/o 执行输入和输出操作,将数据从文件或系统控制台等传送至或传送出应用程序。(有关
  
  java i/o 的其它信息,请参阅
  
  参考资料
  
  缓冲区基础
  
  抽象的
  
  buffer
  
  java.nio
  
  包支持缓冲区的基础。
  
  buffer
  
  的工作方式就象内存中用于读写基本数据类型的
  
  randomaccessfile
  
  randomaccessfile
  
  一样,使用
  
  buffer
  
  ,所执行的下一个操作(读/写)在当前某个位置发生。执行这两个操作中的任一个都会改变那个位置,所以在写操作之后进行读操作不会读到刚才所写的内容,而会读到刚才所写内容之后的数据。
  
  buffer
  
  提供了四个指示方法,用于访问线姓结构(从最高值到最低值):
  
  capacity()
  
  :表明缓冲区的大小
  
  limit()
  
  :告诉您到目前为止已经往缓冲区填了多少字节,或者让您用
  
  :limit(int newlimit)
  
  来改变这个限制
  
  position()
  
  :告诉您当前的位置,以执行下一个读/写操作
  
  mark()
  
  :为了稍后用
  
  reset()
  
  进行重新设置而记住某个位置
  
  缓冲区的基本操作是
  
  get()
  
  put()
  
  ;然而,这些方法在子类中都是针对每种数据类型的特定方法。为了说明这一情况,让我们研究一个简单示例,该示例演示了从同一个缓冲区读和写一个字符。在清单
  
  1 中,
  
  flip()
  
  方法交换限制和位置,然后将位置置为 0,并废弃标记,让您读刚才所写的数据:
  
  清单 1. 读/写示例
  
  
  
  import java.nio.*;
  
  ...
  
  charbuffer buff = ...;
  
  buff.put('a');
  
  buff.flip();
  
  char c = buff.get();
  
  system.out.println("an a: " + c);
  
  
  
  现在让我们研究一些具体的
  
  buffer
  
  子类。
  
  缓冲区类型
  
  merlin 具有 7 种特定的
  
  buffer
  
  类型,每种类型对应着一个基本数据类型(不包括
  
  boolean):
  
  bytebuffer
  
  charbuffer
  
  doublebuffer
  
  floatbuffer
  
  intbuffer
  
  longbuffer
  
  shortbuffer
  
  在本文后面,我将讨论第 8 种类型
  
  mappedbytebuffer
  
  ,它用于内存映射文件。如果您必须使用的类型不是这些基本类型,则可以先从
  
  bytebuffer
  
  获得字节类型,然后将其转换成
  
  object
  
  或其它任何类型。
  
  正如前面所提到的,每个缓冲区包含
  
  get()
  
  put()
  
  方法,它们可以提供类型安全的版本。通常,需要重载这些
  
  get()
  
  put()
  
  方法。例如,有了
  
  charbuffer
  
  ,可以用
  
  get()
  
  获得下一个字符,用
  
  get(int index)
  
  获得某个特定位置的字符,或者用
  
  get(char[] destination)
  
  获得一串字符。静态方法也可以创建缓冲区,因为不存在构造函数。那么,仍以
  
  charbuffer
  
  为例,用
  
  charbuffer.wrap(astring)
  
  可以将
  
  string
  
  对象转换成
  
  charbuffer
  
  。为了演示,清单 2 接受第一个命令行参数,将它转换成
  
  charbuffer
  
  ,并显示参数中的每个字符:
  
  清单 2. charbuffer 演示
  
  
  
  import java.nio.*;
  
  public class readbuff {
  
  public static void main(string args[]) {
  
  if (args.length != 0) {
  
  charbuffer buff = charbuffer.wrap(args[0]);
  
  for (int i=0, n=buff.length(); i
  
  
  
  请注意,这里我使用了
  
  get()
  
  ,而没有使用
  
  get(index)
  
  。我这样做的原因是,在每次执行
  
  get()
  
  操作之后,位置都会移动,所以不需要手工来声明要检索的位置。
  
  直接 vs. 间接
  
  既然已经了解了典型的缓冲区,那么让我们研究直接缓冲区与间接缓冲区之间的差别。在创建缓冲区时,可以要求创建直接缓冲区,创建直接缓冲区的成本要比创建间接缓冲区高,但这可以使运行时环境直接在该缓冲区上进行较快的本机 i/o 操作。因为创建直接缓冲区所增加的成本,所以直接缓冲区只用于长生存期的缓冲区,而不用于短生存期、一次姓且用完就丢弃的缓冲区。而且,只能在
  
  bytebuffer
  
  这个级别上创建直接缓冲区,如果希望使用其它类型,则必须将
  
  buffer
  
  转换成更具体的类型。为了演示,清单
  
  3 中代码的行为与清单 2 的行为一样,但清单 3 使用直接缓冲区:
  
  清单 3. 列出网络接口
  
  
  
  import java.nio.*;
  
  public class readdirectbuff {
  
  public static void main(string args[]) {
  
  if (args.length != 0) {
  
  string arg = args[0];
  
  int size = arg.length();
  
  bytebuffer bytebuffer = bytebuffer.allocatedirect(size*2);
  
  charbuffer buff = bytebuffer.ascharbuffer();
  
  buff.put(arg);
  
  buff.rewind();
  
  for (int i=0, n=buff.length(); i
  
  
  
  在上面的代码中,请注意,不能只是将
  
  string
  
  包装在直接
  
  bytebuffer
  
  中。必须首先创建一个缓冲区,先填充它,然后将位置倒回起始点,这样才能从头读。还要记住,字符长度是字节长度的两倍,因此示例中会有
  
  size*2
  
  内存映射文件
  
  第 8 种
  
  buffer
  
  mappedbytebuffer
  
  只是一种特殊的
  
  bytebuffer
  
  mappedbytebuffer
  
  将文件所在区域直接映射到内存。通常,该区域包含整个文件,但也可以只映射部分文件。所以,必须指定要映射文件的哪部分。而且,与其它
  
  buffer
  
  对象一样,这里没有构造函数;必须让
  
  java.nio.channels.filechannel
  
  map()
  
  方法来获取
  
  mappedbytebuffer
  
  。此外,无需过多涉及通道就可以用
  
  getchannel()
  
  方法从
  
  fileinputstream
  
  fileoutputstream
  
  filechannel
  
  。通过从命令行传入文件名来读取文本文件的内容,清单 4 显示了
  
  mappedbytebuffer
  
  清

扫描关注微信公众号