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

java NIO (3)

阅读更多
在上一篇文章中介绍了缓冲区内部对于状态变化的跟踪机制,而对于NIO中缓冲区来说,还有很多的内容值的学习,如缓冲区的分片与数据共享,只读缓冲区等。在本文中我们来看一下缓冲区一些更细节的内容。
缓冲区的分配
在前面的几个例子中,我们已经看过了,在创建一个缓冲区对象时,会调用静态方法allocate()来指定缓冲区的容量,其实调用 allocate()相当于创建了一个指定大小的数组,并把它包装为缓冲区对象。或者我们也可以直接将一个现有的数组,包装为缓冲区对象,如下示例代码所示:
[java] view plaincopyprint?
public class BufferWrap { 
 
    public void myMethod() 
    { 
        // 分配指定大小的缓冲区 
        ByteBuffer buffer1 = ByteBuffer.allocate(10); 
         
        // 包装一个现有的数组 
        byte array[] = new byte[10]; 
        ByteBuffer buffer2 = ByteBuffer.wrap( array ); 
    } 

缓冲区分片
在NIO中,除了可以分配或者包装一个缓冲区对象外,还可以根据现有的缓冲区对象来创建一个子缓冲区,即在现有缓冲区上切出一片来作为一个新的缓冲区,但现有的缓冲区与创建的子缓冲区在底层数组层面上是数据共享的,也就是说,子缓冲区相当于是现有缓冲区的一个视图窗口。调用slice()方法可以创建一个子缓冲区,让我们通过例子来看一下:
[java] view plaincopyprint?
import java.nio.*; 
 
public class Program { 
    static public void main( String args[] ) throws Exception { 
        ByteBuffer buffer = ByteBuffer.allocate( 10 ); 
         
        // 缓冲区中的数据0-9 
        for (int i=0; i<buffer.capacity(); ++i) { 
            buffer.put( (byte)i ); 
        } 
         
        // 创建子缓冲区 
        buffer.position( 3 ); 
        buffer.limit( 7 ); 
        ByteBuffer slice = buffer.slice(); 
         
        // 改变子缓冲区的内容 
        for (int i=0; i<slice.capacity(); ++i) { 
            byte b = slice.get( i ); 
            b *= 10; 
            slice.put( i, b ); 
        } 
         
        buffer.position( 0 ); 
        buffer.limit( buffer.capacity() ); 
         
        while (buffer.remaining()>0) { 
            System.out.println( buffer.get() ); 
        } 
    } 

在该示例中,分配了一个容量大小为10的缓冲区,并在其中放入了数据0-9,而在该缓冲区基础之上又创建了一个子缓冲区,并改变子缓冲区中的内容,从最后输出的结果来看,只有子缓冲区“可见的”那部分数据发生了变化,并且说明子缓冲区与原缓冲区是数据共享的,输出结果如下所示:

只读缓冲区
只读缓冲区非常简单,可以读取它们,但是不能向它们写入数据。可以通过调用缓冲区的asReadOnlyBuffer()方法,将任何常规缓冲区转 换为只读缓冲区,这个方法返回一个与原缓冲区完全相同的缓冲区,并与原缓冲区共享数据,只不过它是只读的。如果原缓冲区的内容发生了变化,只读缓冲区的内容也随之发生变化:
[java] view plaincopyprint?
import java.nio.*; 
 
public class Program { 
    static public void main( String args[] ) throws Exception { 
        ByteBuffer buffer = ByteBuffer.allocate( 10 ); 
         
        // 缓冲区中的数据0-9 
        for (int i=0; i<buffer.capacity(); ++i) { 
            buffer.put( (byte)i ); 
        } 
 
        // 创建只读缓冲区 
        ByteBuffer readonly = buffer.asReadOnlyBuffer(); 
         
        // 改变原缓冲区的内容 
        for (int i=0; i<buffer.capacity(); ++i) { 
            byte b = buffer.get( i ); 
            b *= 10; 
            buffer.put( i, b ); 
        } 
         
        readonly.position(0); 
        readonly.limit(buffer.capacity()); 
         
        // 只读缓冲区的内容也随之改变 
        while (readonly.remaining()>0) { 
            System.out.println( readonly.get()); 
        } 
    } 

如果尝试修改只读缓冲区的内容,则会报ReadOnlyBufferException异常。只读缓冲区对于保护数据很有用。在将缓冲区传递给某个 对象的方法时,无法知道这个方法是否会修改缓冲区中的数据。创建一个只读的缓冲区可以保证该缓冲区不会被修改。只可以把常规缓冲区转换为只读缓冲区,而不能将只读的缓冲区转换为可写的缓冲区。
直接缓冲区
直接缓冲区是为加快I/O速度,使用一种特殊方式为其分配内存的缓冲区,JDK文档中的描述为:给定一个直接字节缓冲区,Java虚拟机将尽最大努 力直接对它执行本机I/O操作。也就是说,它会在每一次调用底层操作系统的本机I/O操作之前(或之后),尝试避免将缓冲区的内容拷贝到一个中间缓冲区中 或者从一个中间缓冲区中拷贝数据。要分配直接缓冲区,需要调用allocateDirect()方法,而不是allocate()方法,使用方式与普通缓冲区并无区别,如下面的拷贝文件示例:
[java] view plaincopyprint?
import java.io.*; 
import java.nio.*; 
import java.nio.channels.*; 
 
public class Program { 
    static public void main( String args[] ) throws Exception { 
        String infile = "c:\\test.txt"; 
        FileInputStream fin = new FileInputStream( infile ); 
        FileChannel fcin = fin.getChannel(); 
         
        String outfile = String.format("c:\\testcopy.txt"); 
        FileOutputStream fout = new FileOutputStream( outfile );     
        FileChannel fcout = fout.getChannel(); 
         
        // 使用allocateDirect,而不是allocate 
        ByteBuffer buffer = ByteBuffer.allocateDirect( 1024 ); 
         
        while (true) { 
            buffer.clear(); 
             
            int r = fcin.read( buffer ); 
             
            if (r==-1) { 
                break; 
            } 
             
            buffer.flip(); 
             
            fcout.write( buffer ); 
        } 
    } 

内存映射文件I/O
内存映射文件I/O是一种读和写文件数据的方法,它可以比常规的基于流或者基于通道的I/O快的多。内存映射文件I/O是通过使文件中的数据出现为 内存数组的内容来完成的,这其初听起来似乎不过就是将整个文件读到内存中,但是事实上并不是这样。一般来说,只有文件中实际读取或者写入的部分才会映射到内存中。如下面的示例代码:
[java] view plaincopyprint?
import java.io.*; 
import java.nio.*; 
import java.nio.channels.*; 
 
public class Program { 
    static private final int start = 0;<span style="font-family:FangSong_GB2312;font-size:13px;"> 
    static private final int size = 1024; 
     
    static public void main( String args[] ) throws Exception { 
        RandomAccessFile raf = new RandomAccessFile( "c:\\test.txt", "rw" ); 
        FileChannel fc = raf.getChannel(); 
         
        MappedByteBuffer mbb = fc.map( FileChannel.MapMode.READ_WRITE, 
          start, size ); 
         
        mbb.put( 0, (byte)97 ); 
        mbb.put( 1023, (byte)122 ); 
         
        raf.close(); 
    } 
}</span>
分享到:
评论

相关推荐

    java NIO和java并发编程的书籍

    java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java...

    JavaNIO chm帮助文档

    Java NIO系列教程(一) Java NIO 概述 Java NIO系列教程(二) Channel Java NIO系列教程(三) Buffer Java NIO系列教程(四) Scatter/Gather Java NIO系列教程(五) 通道之间的数据传输 Java NIO系列教程(六)...

    Java NIO英文高清原版

    Java NIO英文高清原版

    java nio 包读取超大数据文件

    Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据...

    java NIO.zip

    java NIO.zip

    Java NIO 中文 Java NIO 中文 Java NIO 中文文档

    Java NIO 深入探讨了 1.4 版的 I/O 新特性,并告诉您如何使用这些特性来极大地提升您所写的 Java 代码的执行效率。这本小册子就程序员所面临的有代表性的 I/O 问题作了详尽阐述,并讲解了 如何才能充分利用新的 I/O ...

    java NIO 中文版

    讲解了 JavaIO 与 JAVA NIO区别,JAVA NIO设计理念,以及JDK中java NIO中语法的使用

    java nio 实现socket

    java nio 实现socketjava nio 实现socketjava nio 实现socketjava nio 实现socketjava nio 实现socket

    java NIO 视频教程

    Java NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式。 Java NIO: Channels and Buffers(通道和缓冲区) 标准的IO基于字节流和字符流进行操作的,...

    java nio中文版

    java NIO是 java New IO 的简称,在 jdk1.4 里提供的新 api 。 Sun 官方标榜的特性如下: – 为所有的原始类型提供 (Buffer) 缓存支持。 – 字符集编码解码解决方案。 – Channel :一个新的原始 I/O 抽象。 – 支持...

    java_nio学习文档

    java_nio学习文档

    Java Nio selector例程

    java侧起server(NioUdpServer1.java),基于Java Nio的selector 阻塞等候,一个android app(NioUdpClient1文件夹)和一个java程序(UI.java)作为两个client分别向该server发数据,server收到后分别打印收到的消息...

    java NIO技巧及原理

    java NIO技巧及原理解析,java IO原理,NIO框架分析,性能比较

    java nio 读文件

    java nio 读文件,java nio 读文件

    java基于NIO实现Reactor模型源码.zip

    java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现...

    JAVA NIO 学习资料

    JAVA NIO学习资料JAVA NIO学习资料

    Java NIO测试示例

    Java NIO测试示例

    基于Java NIO实现五子棋游戏.zip

    基于Java NIO实现五子棋游戏.zip基于Java NIO实现五子棋游戏.zip 基于Java NIO实现五子棋游戏.zip基于Java NIO实现五子棋游戏.zip 基于Java NIO实现五子棋游戏.zip基于Java NIO实现五子棋游戏.zip 基于Java NIO实现...

    Java NIO.pdf

    java nio编程 非阻塞模式的通信 电子书 带目录标签

    Java NIO 英文文字版

    Many serious Java programmers, especially enterprise Java programmers, consider the new I/O API--called NIO for New Input/Output--the most important feature in the 1.4 version of the Java 2 Standard ...

Global site tag (gtag.js) - Google Analytics