ByteBuffer有两个创建缓冲区的方法:
static ByteBuffer allocate(int capacity)
static ByteBuffer allocateDirect(int capacity)
  这两个方法都是创建缓冲区的方法,使用直接缓冲区的时候,JVM虚拟机会直接在此缓冲区上执行本机IO操作,也就是说,在每次调用基础操作系统的一个本机IO之前或者之后,虚拟机都会避免将缓冲区的内容复制到中间缓冲区(或者从中间缓冲区复制内容)。 直接字节缓冲区使用上边方法中的allocateDirect工厂方法创建,此方法返回的缓冲区进行分配和取消分配所需要的成本往往比间接缓冲区要高,直接缓冲区的内容可以驻留 在常规的垃圾回收堆之外,因此,它们对应用程序的内容需求量造成的影响可能并不明显,所以建议将直接缓冲区主要分配给那些容易受基础系统的本 机IO操作影响的大型、持久的缓冲区。一般情况下,最好仅在直接缓冲区能在程序性能方面带来明显好处的时候分配它们。
  直接缓冲区还可以使用mapping 将文件区域直接映射到内存中来创建,Java平台的实现有助于通过JNI从本机代码直接创建字节缓冲区,如果以上这些缓冲区中的某个缓冲区实例指的是不可 访问的内存区域,则视图访问该区域不会更改该缓冲区的内容,并且会在访问期间或稍候的某个时间导致抛出不确定的异常。
  字节缓冲区是直接缓冲区还是非直接缓 冲区可以通过ByteBuffer的isDirect方法来确定,提供该方法是为了能够在性能关键型代码中执行显示缓冲区管理。
  访问二进制数据:
  此类定义除了boolean之外,读写所有其他基本类型值的方法,这些基本值可 以根据缓冲区的当前字节顺序与字节序列相互进行转换,并可以通过order方法获取和修改。特定的字节顺序由ByteOrder类的实例进行表示,字节缓 冲区的初始顺序是BIG_ENDIAN(该顺序可以参考《Java内存模型》http://blog.csdn.net/silentbalanceyh/archive/2009/10/13/4661230.aspx)的。为了访问异类二进制数据,此类还针对每种类型定义了一系列绝对和相对的put和get方法, 并针对float、 char、short、int、long和double等类型定义了相对方法,该方法可以自行参考API内容。绝对get和put方法的 index参数是根据字节定义的,而不是根据所读写的类型定义的。
  为了访问同类二进制数据(即相同类型的值序列),此类还定义了可 以为指定类型的缓冲区创建视图的方法,视图缓冲区只是其内容受该字节缓冲区支持的另一种缓冲区,字节缓冲区内容的更改在视图缓冲区中是可见的,反之亦然;这两种缓冲区的位置、限制和标记 值都是独立的。使用视图缓冲区有三大优势:
视 图缓冲区不是根据字节进行索引,而是根据其特定于类型的值的大小进行索引
视 图缓冲区提供了相对批量put和get方法,这些方法可在缓冲区和数组或相同类型的其他缓冲区之间传输值的连续序列
视图缓冲区可能更高效,这是因为,当且仅当其支持的字节缓冲区为直接缓冲区时它才是直接缓冲区。
  实际上ByteBuffer是继承于Buffer类,里面存放的是字节,如果要 将它们转换成字符串则需要使用Charset,Charset是字符编码,它提供了把字节流转换成为字符流(解码)和 将字符串转换成字节流(编码)的方法。该类有一下三个重要的属性:
容量(capacity):表示该缓冲区可以存放多少数据
极限(limit):表示读写缓存的位置, 不能对超过位置进行数据的读或写操作
位置(position):表示下一个缓冲区的读写单元, 每读写一次缓存区,位置都会变化,位置是一个非负整数

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
  
public class QuickCopy {
    public static void main(String args[]) throws Exception{
        FileInputStream fin = new FileInputStream("D:/work/test.txt");
        FileOutputStream fout = new FileOutputStream("D:/work/output.txt");
        FileChannel inChannel = fin.getChannel();
        FileChannel outChannel = fout.getChannel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        while(true){
            int ret = inChannel.read(buffer);
            if( ret == -1)
                break;
            buffer.flip(); //该方法为父类Buffer的方法
            outChannel.write(buffer);
            buffer.clear(); //该方法为父类Buffer的方法
        }
    }
}

  上边的代码分配了1024个字节的直接缓冲区,然后使用本地拷贝的方式进行文件拷贝,应该是比 普通的文件拷贝更高效,这里解释几个比较常用的ByteBuffer类里面的方法【这里不介绍分配缓冲区的方法 了】:
public abstract ByteBuffer compact() throws ReadOnlyBufferException:
——该方法压缩此缓冲区(可选的),将缓冲区的当前位置和界限之间的字节复制到缓冲区的开始处,即将索引p = position()处 的字节复制到索引0处,将索引n+1处的字节复制到索引1的 位置,依次类推直到索引limit() - 1处的字节复制到索引 n = limit() - 1 - p处, 然后将缓冲区的位置设置为n + 1,并将其界限设置为其容量,如果已定义了标记,则丢弃。将缓冲区的位置设置为复制的字节数,而不是零,以便调 用此方法后可以紧接着调用另一个相对put方法。
public abstract ByteBuffer duplicate():
——创建共享此缓冲区内容的新的字节缓冲区,新缓冲区的内容将为此缓冲区的内容,此缓冲区内容的更改在新缓冲 区中是可见的,反之亦然;这两个缓冲区的位置、界限和标记值是相互独立的。新缓冲区的容量、界限、位置和标记值将与此缓冲区相同。当且 仅当此缓冲区为直接时,新缓冲区才是直接的,当切仅当此缓冲区是只读时,新缓冲区才是只读的。
public abstract ByteBuffer slice():
——创建新的字节缓冲区,其内容是此缓冲区的共享子序列,新缓冲区的内容将从此缓冲区的当前位置开始,此缓冲 区内容的更改在新缓冲区中是可见的,反之亦然;这两个缓冲区的位置、界限和标记值是相互独立的。
public abstract ByteBuffer wrap(byte[] array):
——将byte数组包装到缓冲区中,新的缓冲区将由给定的byte数组支持,也就是说,缓冲区修改 将导致数组修改,反之亦然。新缓冲区的容量和界限将为array.length,其位置将为零,其标记是不确定的,其底层实现数据将为给定数组,并且其数 组偏移量将为零。
  这里再提供几个基本操作的例子:

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
 
public class BasicType {
    public static void main(String args[]) throws Exception{
        // 使用字节数组创建ByteBuffer
        byte[] bytes = new byte[10];
        ByteBuffer buffer = ByteBuffer.wrap(bytes);
        // 创建字符ByteBuffer
        ByteBuffer charBuffer = ByteBuffer.allocate(15);
        CharBuffer charBuffer2 = buffer.asCharBuffer();
        // 设置获取字符类型的Buffer
        ByteBuffer charBuffer3 = ByteBuffer.allocate(100);
        charBuffer3.putChar((char)123);
        charBuffer3.flip();
        char c = charBuffer3.getChar();
    }
}

  上边是针对基本类型的操作,查阅API可以看到基本操作相关的类里面提供的方法

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
 
public class StringByteBuffer {
    public static void main(String args[]) throws Exception{
        // 使用ByteBuffer存储字符串
        ByteBuffer buffer = ByteBuffer.allocate(100);
        CharBuffer cBuffer = buffer.asCharBuffer();
        cBuffer.put("Hello World");
        cBuffer.flip();
        String result = cBuffer.toString();
    }
} 2013-01-13 名品推荐:潮顺品 榕宜 灵澜

java NIO 直接与非直接缓冲区的更多相关文章

  1. Java NIO -- 阻塞和非阻塞

    传统的 IO 流都是阻塞式的.也就是说,当一个线程调用 read() 或 write()时,该线程被阻塞,直到有一些数据被读取或写入,该线程在此期间不能执行其他任务.因此,在完成网络通信进行 IO操作 ...

  2. Java NIO: Non-blocking Server 非阻塞网络服务器

    本文翻译自 Jakob Jenkov 的 Java NIO: Non-blocking Server ,原文地址:http://tutorials.jenkov.com/java-nio/non-bl ...

  3. Java NIO(二)缓冲区

    概念 缓冲区:一个用于特定基本数据类型的容器,由java.nio包定义的所有缓冲区都是Buffer抽象类的子类.其作用于与NIO的通道进行交互,数据从通道读入缓冲区,数据从缓冲区写入通道 Buffer ...

  4. Java NIO ———— Buffer 缓冲区详解 入门

    引言缓冲区是一个用于特定基本类型的容器.由java.nio 包定义,所有缓冲区都是 Buffer 抽象类的子类. Java NIO 中的 Buffer ,主要用于与NIO 通道进行交互.数据从通道存入 ...

  5. Java NIO入门(二):缓冲区内部细节

    Java NIO 入门(二)缓冲区内部细节 概述 本文将介绍 NIO 中两个重要的缓冲区组件:状态变量和访问方法 (accessor). 状态变量是前一文中提到的"内部统计机制"的 ...

  6. Java NIO 之 Buffer(缓冲区)

    一 Buffer(缓冲区)介绍 Java NIO Buffers用于和NIO Channel交互. 我们从Channel中读取数据到buffers里,从Buffer把数据写入到Channels. Bu ...

  7. java nio使用方法(转)

    最近由于工作关系要做一些Java方面的开发,其中最重要的一块就是Java NIO(New I/O),尽管很早以前了解过一些,但并没有认真去看过它的实现原理,也没有机会在工作中使用,这次也好重新研究一下 ...

  8. Java NIO学习笔记一 Java NIO概述

    Java NIO概述 Java NIO(新的IO)是Java的替代IO API(来自Java 1.4),这意味着替代标准的 java IO和java Networking API.Java NIO提供 ...

  9. Java NIO 概览

    Java面试通关手册(Java学习指南) Github地址:https://github.com/Snailclimb/Java_Guide 一 NIO简介 Java NIO 是 java 1.4 之 ...

随机推荐

  1. Redis常用操作-------Key(键)

    1.DEL key [key ...] 删除给定的一个或多个 key . 不存在的 key 会被忽略. 可用版本: >= 1.0.0 时间复杂度: O(N), N 为被删除的 key 的数量. ...

  2. Python-集合-17

    ''' 集合:可变的数据类型,他里面的元素必须是不可变的数据类型,无序,不重复. {} ''' set1 = set({1,2,3}) # set2 = {1,2,3,[2,3],{'name':'a ...

  3. bash处理一条命令的步骤

    Shell执行一条命令步骤 参考链接: <Learning the bash Shell, 3rd Edition  -- 7.3. Command-Line Processing> &l ...

  4. Hybrid APP基础篇(一)->什么是Hybrid App

    最新更新 一个开源的快速混合开发框架:https://github.com/quickhybrid/quickhybrid Android.iOS.JS三端内容初步都已经完成,有完善的设计思路.教程以 ...

  5. sixsix团队M2阶段Postmortem

    设想和目标 1. 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 要解决的问题:目前外卖网站比较多,用户很难快速找到合适的外卖,我们集合各个网站的外卖信息,为用户提 ...

  6. Linux内核分析作业第六周

    创建新进程的过程 一.进程的描述 为了管理进程,内核必须对每个进程进行清晰的描述,进程描述符提供了内核所需了解的进程信息. 1.进程控制块PCB——task_struct 操作系统的三大管理功能 进程 ...

  7. PAT 1071 小赌怡情

    https://pintia.cn/problem-sets/994805260223102976/problems/994805264312549376 常言道“小赌怡情”.这是一个很简单的小游戏: ...

  8. Red Hat 5.8 CentOS 6.5 共用 输入法

    pick up from http://jingyan.baidu.com/article/20b68a885a3607796cec622c.html

  9. 安裝CentOS7后修復win7引导

    想尝试双系统的心情想必大家都能理解,但是安装了双系统之后的收尾工作也是必不可少的,由于对Linux并不算很熟悉,所以在这方面花了不少时间,这里将CentOS7下修復windows7引导的解决方案记录下 ...

  10. lamp下mysql安全加固

    lamp下mysql安全加固 1.修改root用户口令,删除空口令 缺省安装的MySQL的root用户是空密码的,为了安全起见,必须修改为强密码,所谓的强密码,至少8位,由字母.数字和符号组成的不规律 ...