`
zcdxzsz
  • 浏览: 73081 次
  • 来自: ...
社区版块
存档分类
最新评论

java.nio.Buffer缓冲区基础[转]

    博客分类:
  • java
阅读更多
缓冲区基础

抽象类Buffer是java.nio包支持缓冲区的基础。 Buffer 的工作方式就象内存中用于读写基本数据类型的 RandomAccessFile 。象 RandomAccessFile 一样,使用 Buffer ,所执行的下一个操作(读/写)在当前某个位置发生。执行读/写操作中的任一个都会改变那个位置,所以在写操作之后进行读操作不会读到刚才所写的内容,而会读到刚才所写内容之后的数据。 Buffer 提供了四个指示方法,用于访问线性结构(从最高值到最低值):

capacity() :表明缓冲区的容量大小, 一旦确定了大小, 将不能再改变;
limit() :告诉您到目前为止已经往缓冲区填了多少字节,或者让您用 :limit(int newLimit) 来改变这个限制
position() :告诉您当前的位置,以执行下一个读/写操作
mark() :为了稍后用 reset() 进行重新设置而记住某个位置
flip() :交换限制指针和位置指针,然后将位置置为 0,并废弃已经做的mark标记

缓冲区的基本操作是读 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       //存放任何除boolean类型外的其他基本类型
CharBuffer       //存放char
DoubleBuffer     //存放double
FloatBuffer      //存放float
IntBuffer        //存放int
LongBuffer       //存放long
ShortBuffer      //存放short

在本文后面,我将讨论第 8 种类型 MappedByteBuffer ,它用于内存映射文件。如果您必须使用的类型不是这些基本类型,则可以先从 ByteBuffer 获得字节类型,然后将其转换成 Object 或其它任何类型。


创建缓冲区
一共有两种类型的缓冲区,直接缓冲区和非直接缓冲区。

在创建缓冲区时,可以要求创建直接缓冲区,创建直接缓冲区的成本要比创建间接缓冲区高,但这可以使运行时环境直接在该缓冲区上进行较快的本机 I/O 操作。因为创建直接缓冲区所增加的成本,所以直接缓冲区只用于长生存期的缓冲区,而不用于短生存期、一次性且用完就丢弃的缓冲区。而且,只能在 ByteBuffer 这个级别上创建直接缓冲区,如果希望使用其它类型,则必须将 Buffer 转换成更具体的类型。

判断一个缓冲区是否是直接缓冲区,可以调用isDirect()方法。

有三种方式来获取一个缓冲区的对象:
a. 调用allocate()或者allocateDirect()方法直接分配,其中allocateDirect()返回的是直接缓冲区。
b. 包装一个数组,如:
      byte[] b = new byte[1024];
      ByteBuffer bb = ByteBuffer.wrap(b);
c. 内存映射,即调用FileChannel的map()方法。

缓冲区基本属性
这几个属性是每个缓冲区都有的并且是常用的操作。
a. 容量(capacity),缓冲区大小
b. 限制(limit),第一个不应被读取或写入的字节的索引,总是小于容量。
c. 位置(position),下一个被读取或写入的字节的索引,总是小于限制。
d. clear()方法:设置limit为capacity,position为0。
e. filp()方法:设置limit为当前position,然后设置position为0。
f. rewind()方法:保持limit不变,设置position为0。

缓冲区数据操作
操作包括了读取和写入数据两种。
读取数据使用get()及其系列方法,除boolean外,每一种类型包括了对应的get()方法,如getInt(),getChar()等,get()方法用来读取字节,支持相对和绝对索引两种方式。
写入数据使用put()及其系列方法,和get()方法是对应的。

package nio;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class BufferDemo ...{

    
    public static void main(String[] args) throws Exception...{
        //分配一个非直接缓冲区
        ByteBuffer bb = ByteBuffer.allocate(100);
        //向缓冲区写入0到100的字节制
        for(int i = 0; i <100; i++)...{
            byte b = (byte) (Math.random() * 100);
            bb.put(b);
        }
        
        System.out.println("写入文件前的缓冲区数据");
        bb.flip();
        while(bb.hasRemaining())
            System.out.print(bb.get() + " ");
        System.out.println();
        
        //获取一个关联到文件buffer.txt的信道
        FileChannel fc = new FileOutputStream("buffer.txt").getChannel();
        //将缓冲区数据写到文件中
        bb.flip();
        fc.write(bb);
        //防止缓存
        fc.force(true);
        //关闭信道
        fc.close();
        bb = null;
        fc = null;
        
        //下面从文件中读取数据
        fc = new FileInputStream("buffer.txt").getChannel();
        ByteBuffer bb2 = ByteBuffer.allocate((int) fc.size());
        fc.read(bb2);
        System.out.println("从文件读取的缓冲区数据");
        bb2.flip();
        while(bb2.hasRemaining())
            System.out.print(bb2.get() + " ");
        System.out.println();
        fc.close();
        bb2 = null;
        fc = null;
        

    }

}


内存映射文件

第 8 种 Buffer 类型 MappedByteBuffer 只是一种特殊的 ByteBuffer 。 MappedByteBuffer 将文件所在区域直接映射到内存。通常,该区域包含整个文件,但也可以只映射部分文件。所以,必须指定要映射文件的哪部分。而且,与其它 Buffer 对象一样,这里没有构造函数;必须让 java.nio.channels.FileChannel 的 map() 方法来获取 MappedByteBuffer 。此外,无需过多涉及通道就可以用 getChannel() 方法从 FileInputStream 或 FileOutputStream 获取 FileChannel 。通过从命令行传入文件名来读取文本文件的内容,清单 4 显示了 MappedByteBuffer :


清单 4. 读取内存映射文本文件
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
public class ReadFileBuff {
  public static void main(String args[]) throws IOException {
     if (args.length != 0) {
      String filename = args[0];
      FileInputStream fis = new FileInputStream(filename);
      FileChannel channel = fis.getChannel();
      int length = (int)channel.size();
      MappedByteBuffer byteBuffer =
        channel.map(FileChannel.MapMode.READ_ONLY, 0, length);
      Charset charset = Charset.forName("ISO-8859-1");
      CharsetDecoder decoder = charset.newDecoder();
      CharBuffer charBuffer = decoder.decode(byteBuffer);
      for (int i=0, n=charBuffer.length(); i<n; i++) {
        System.out.print(charBuffer.get());
      }
    }
  }
}
分享到:
评论

相关推荐

    nio:Clojure对java.nio的支持

    定义新的强制功能缓冲区,字节缓冲区,字符缓冲区,双缓冲区,浮点缓冲区,整数缓冲区,长缓冲区,短缓冲区,通道,可读通道和可写通道。 这些功能已为您期望的许多类实现。 还定义了函数mmap来对文件进行内存映射...

    Java NIO实战开发多人聊天室

    01-Java NIO-课程简介.mp4 05-Java NIO-Channel-FileChannel...18-Java NIO-Buffer-只读缓冲区.mp4 19-Java NIO-Buffer-直接缓冲区.mp4 21-Java NIO-Selector-概述.mp4 23-Java NIO-Selector-示例代码(客户端).mp4 24

    尚硅谷Java视频_NIO 视频教程

    尚硅谷_NIO_缓冲区(Buffer)的数据存取 ·03. 尚硅谷_NIO_直接缓冲区与非直接缓冲区 ·04. 尚硅谷_NIO_通道(Channel)的原理与获取 ·05. 尚硅谷_NIO_通道的数据传输与内存映射文件 ·06. 尚硅谷_NIO_分散读取与聚集...

    Java NIO(通道+缓冲区+选择器)

    Java NIO通道:通道基础、文件通道、Socket通道、工具类 Java NIO缓冲区:基础、缓冲区(Buffer)、创建缓冲区、直接缓冲区(DirectByteBuffer) Java NIO选择器:核心概念、选择器使用、Demo、选择器深入、

    详细了解JAVA NIO之Buffer(缓冲区)

    主要介绍了JAVA NIO之Buffer(缓冲区)的相关资料,文中讲解非常细致,帮助大家更好的学习JAVA NIO,感兴趣的朋友可以了解下

    java8源码-nio:java8nio使用的总结

    NIO_缓冲区(Buffer)的数据存取 缓冲区(Buffer):在 Java NIO 中负责数据的存取。缓冲区就是数组。用于存储不同数据类型的数据 4. NIO_直接缓冲区与非直接缓冲区 非直接缓冲区:通过 allocate() 方法分配缓冲区,将...

    java NIO 视频教程

    标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。 Java NIO: Non-blocking IO(非阻塞IO) Java NIO...

    java nio教程pdf

    标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。 Java NIO: Asynchronous IO(异步IO) Java NIO可以...

    Java CP/IP Socket编程

    1. 使用定长的写缓冲区改写TCPEchoClientNonblocking.java。..........149 2.使用Buffer和DatagramChannel编写一个回显客户端。..........149 第6章深入剖析..........149 6.1 缓冲和TCP..........152 6.2 死锁...

    Java NIO Buffer过程详解

    主要介绍了Java NIO Buffer过程详解,缓冲区在java nio中负责数据的存储。缓冲区就是数组。用于存储不同数据类型的数据。,需要的朋友可以参考下

    java核心知识点整理.pdf

    25 JAVA8 与元数据.................................................................................................................................25 2.4. 垃圾回收与算法 .................................

    javasnmp源码-nio-learn:JavaNIO使用示例,NIO的使用,TCP,UDP的简单示例

    Buffer是数据的容器,在nio中负责数据的存取,java为不同数据类型提供了相对应的缓冲区类型 如:ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer 、DoubleBuffer 等。 Buffer的基本使用 ...

    JAVA核心知识点整理(有效)

    25 JAVA8 与元数据.................................................................................................................................25 2.4. 垃圾回收与算法 .................................

    java8中NIO缓冲区(Buffer)的数据存储详解

    在本篇文章中小编给大家分享了关于java8中NIO缓冲区(Buffer)的数据存储的相关知识点,需要的朋友们参考下。

    Java NIO 网络编程初探

    NIO支持面向缓冲区的、基于通道的IO操作。能够更加高效的进行IO操作。NIO同样拥有文件读写,网络通信等IO操作,今天我们来看看NIO中的TCP网络通信的使用方法。 2. Java NIO 三大核心 Java NIO 有三大核心要素:...

    Java NIO缓冲

    缓冲区(buffer)是从即将写入通道(channel)或刚刚从通道中读出的一段数据。它是一个持有数据,并扮演NIO通道端点的对象。缓冲区为数据访问和读写过程提供正式机制。  它是NIO和老版Java I/O的一个主要区别。...

    Java 基础核心总结 +经典算法大全.rar

    缓冲区(Buffer)通道(Channel) 示例:文件拷贝案例 BIO 和 NIO 拷贝文件的区别操作系统的零拷贝 选择器(Selectors) 选择键(SelectionKey) 示例:简易的客户端服务器通信 集合 集合框架总览 -、Iterator Iterable ...

Global site tag (gtag.js) - Google Analytics