学习笔记之ByteBuffer使用和实现以及文件内存映射

转载自  学习笔记之ByteBuffer使用和实现以及文件内存映射

ByteBuffer和CharBuffer等其它Buffer的直接子类一样,顾名思义,就是存取字节的Buffer。很多数据最终在和底层交互上都是使用了字节,而更大的数据是由字节组合而成。谈到字节的组合,就不得不谈到字节大小的定义和字节的顺序。关于字节是8位构成的这个结论,似乎现在的计算机教材都理所当然地描述出来,我们也默认接受了这样的一个事实。但实际上字节由8个二进制位构成也是有渊源和优点的,这与IBM的360主机有关,详细的可以参考这个。下面说说组成数据的字节顺序。

对于多字节的数据在系统中的存储,通常按数据的高位和低位在系统内存中的高地址和低地址存放分为大端(big endian)和小端(little endian)两种方式。

在Java API中,有ByteOrder这样一个public类,在其中定义了大端和小端两个常量。通过这个java.nio.ByteOrder类的nativeOrder()方法,也可以确定当前系统平台的字节顺序。

在不同的平台上可能有不同的字节顺序标准。但在ByteBuffer类中,默认是使用了ByteOrder.BIG_ENDIAN字节序。但可以通过ByteBuffer的重载方法获取和设置字节序:

  • public final ByteOrder order( )
  • public final ByteBuffer order (ByteOrder bo)

1. ByteBuffer的实现

提到ByteBuffer的实现,我们先来看下Win下JDK实现的类层次结构图。

Win下JDK的ByteBuffer类层次结构图

而在Oracle的Java SE API中,实际上只提到了MappedByteBuffer。所以堆实现和具体的直接实现(DirectByteBuffer)我们只简单了解就行了,因为这个不在API中,和平台实现相关。

HeapByteBuffer 是虚拟机的堆中实现,DirectByteBuffer是系统级别实现(使用unsafe的 unsafe.allocateMemory(size)),使用时后者比前者节省了拷贝过程,但后者的构建和析构成本更高,总体性能需要具体问题综合分析。而且DirectByteBuffer会受到平台方面的约束,使用时需要小心注意。

而API中出现了的java.nio.MappedByteBuffer则是针对文件映射工作的,也是一种Direct的ByteBuffer。除了继承ByteBuffer类的方法外,API还提供了下面3个方法:

  • public final MappedByteBuffer force()
  • public final boolean isLoaded()
  • public final MappedByteBuffer load()

关于文件映射相关的具体内容,下面会详细说。

2. ByteBuffer和Buffer的其它直接子类之间的关系

前面的一篇Buffer的文章提到了它的几个直接子类,分别是ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer。除了ByteBuffer,还有另外6种,而这些也都和Java的基本数据类型有一定的对应关系,下面我们对使用上的情况梳理下。

ByteBuffer继承于Buffer。和CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer一样,都是抽象类。

在Java NIO中,除了Buffer还有Channel等类。Buffer也只有和Channel配合才能充分地把Java NIO使用起来。而Channel中的很多方法都是使用ByteBuffer作为参数和返回结果进行传递的,好处就是Byte是字节、是基础,而方法也简单了很多。

而这样的设计有一个要求,就是使用Byte以外的类型也能很好的利用到ByteBuffer,这其中有两种方式:

  • 一种是View Buffer,即直接通过ByteBuffer的数据结构做支持,得到另外一种类型Buffer对象
  • 另一种就是Data Element View,即不通过CharBuffer等类对象和ByteBuffer的互相转换获取,而是直接使用ByteBuffer自带的基本类型put和get方法

下面是两段代码例子。

ByteBuffer byteBuffer = ByteBuffer.allocate (7).order (ByteOrder.BIG_ENDIAN);
CharBuffer charBuffer = byteBuffer.asCharBuffer( );intvalue = buffer.getInt( );

当然,在实际使用过程中也会有需要注意的问题,比如字符数据,就需要考虑字符集编码的问题。下面是《Thinking in Java》中的例子:

publicclass  BufferToText {privatestatic  final  int  BSIZE = 1024;publicstatic  void  main(String[] args)throwsException {FileChannel fc = newFileOutputStream("data2.txt").getChannel();fc.write(ByteBuffer.wrap("Some text".getBytes()));fc.close();fc = newFileInputStream("data2.txt").getChannel();ByteBuffer buff = ByteBuffer.allocate(BSIZE);fc.read(buff);buff.flip();// Doesn’t work:System.out.println(buff.asCharBuffer());// Decode using this system’s default Charset:buff.rewind();String encoding = System.getProperty("file.encoding");System.out.println("Decoded using "+ encoding + ": "+ Charset.forName(encoding).decode(buff));// Or, we could encode with something that will print:fc = newFileOutputStream("data2.txt").getChannel();fc.write(ByteBuffer.wrap("Some text".getBytes("UTF-16BE")));fc.close();// Now try reading again:fc = newFileInputStream("data2.txt").getChannel();buff.clear();fc.read(buff);buff.flip();System.out.println(buff.asCharBuffer());// Use a CharBuffer to write through:fc = newFileOutputStream("data2.txt").getChannel();buff = ByteBuffer.allocate(24); // More than neededbuff.asCharBuffer().put("Some text");fc.write(buff);fc.close();// Read and display:fc = newFileInputStream("data2.txt").getChannel();buff.clear();fc.read(buff);buff.flip();System.out.println(buff.asCharBuffer());}
}

3. 内存映射和ByteBuffer的使用

这段内容将简单说明下文件内存映射的概念和ByteBuffer的其它点。

ByteBuffer的最基本使用,和上一篇NIO中讲CharBuffer等Buffer的直接子类一样,就是put()和get()。为提高效率,除了单个字节读写,有整块的操作方法,即对get()和put()的重载方法。

而内存映射这个概念最初一直困惑了我很久才搞明白,但实际上原理并不复杂,只需要了解操作系统工作的最基本原理。我们通常的直接通过API做IO,会用到一系列的系统调用(system call),之后通过驱动程序和外部设备交互来完成输入输出操作,磁盘上的文件读写也是一样。而文件内存映射之所以得到很好的使用是因为,使用了文件的内存映射可以大大提高效率。提高效率的点就在于,不必每个IO操作都经过系统调用来完成,这个效率是相对较低的,而是巧妙灵活地使用内存管理系统。我们都知道当程序需要使用大量内存而实际物理内存较小的时候,我们的内存管理系统会进行页的换入换出操作,使部分当前使用不到的内存页放到磁盘上去,而缺页中断又会相应的做换入操作 —— 这就是内存映射的基础。

在Java中,在Java NIO的FileChannel类中,提供了一个map()方法,这个方法返回的结果就是一个MappedByteBuffer类的对象,也就是一个ByteBuffer对象。这使得我们对磁盘上文件内容的读写,完全可以像对其他Buffer一样,进行put()和get()。

4. 其它一些实现细节

这是一些未深入整理的实现细节点,在Win下的Oracle/Sun JDK:

  • ByteBuffer的具体实现,也是基于byte数组和对应的offset
  • 有array()和arrayOffset()抽象未实现方法
  • 还有address属性,DirectBuffer才会用到
  • 还有只读等属性和其它方法等

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/329000.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

当当网上书店头部和尾部——JS源码

头部 $(function($){ // οnmοuseοver"myddang_show(dd_menu_top_down)" οnmοuseοut"myddang_hidden(dd_menu_top_down)"//下拉菜单$("#menu").mouseenter(function(){$("#dd_menu_top_down").slideDown(1000);}).mouseleave(…

SQL注入(SQL Injection)

简介 SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。 根据…

c语言程序设计班档案管理系统报告,C语言班级档案管理系统

《C语言班级档案管理系统》由会员分享,可在线阅读,更多相关《C语言班级档案管理系统(28页珍藏版)》请在人人文库网上搜索。1、c语言程序设计”课程设计报告班级档案管理学生姓名: 王标 刘慧慧 魏枫林 奚亚运 指导教师: 夏 芸 所 在…

深入理解ByteBuffer

转载自 深入理解ByteBufferByteBuffer类是在Java NIO中常常使用的一个缓冲区类,使用它可以进行高效的IO操作,但是,如果对常用方法的理解有错误,那么就会出现意想不到的bug。ByteBuffer类的常用方法 先来看看一个基本的程序public…

c语言倒置存放,c语言倒置

为什么使用人脸识别返回数据为空? 问题现象 上传照片中的人像可能存在横置或倒置等情况。 解决方法 尽量选择纯色无干扰背景,保证图片中人像清晰。 上传的人脸图片要求:侧脸不超过30,抬头低头不超过15。 图片中人脸需要保持竖置正…

当当网新用户注册界面——界面源码

<strong><span style"font-size:32px;color:#ff9966;">所有用到的图片都已上传&#xff0c;请在<a target_blank href"http://download.csdn.net/detail/qq_34137397/9667142">这里</a>下载</span></strong><!DOCT…

dotnetCore增加MiddleWare的Run,Use Map MapThen四个扩展方法

什么是中间件 中间件是在管道中处理Request请求与Responses响应的一种组件&#xff0c;每种组件可以选择是否让Request进入到下一个组件去处理。 译得不好&#xff0c;大家可以自己看原文Middleware 更详细的还可以参照园中大神的作品&#xff1b; 有汤姆大叔的解读ASP.NET 5 &…

Java GC系列(1):Java垃圾回收简介

转载自 Java GC系列&#xff08;1&#xff09;&#xff1a;Java垃圾回收简介这篇教程是系列第一部分。首先会解释基本的术语&#xff0c;比如JDK、JVM、JRE和HotSpotVM。接着会介绍JVM结构和Java 堆内存结构。理解这些基础对于理解后面的垃圾回收知识很重要。 Java关键术语 Ja…

下载的c语言程序代码怎么运行,CFree怎么运行程序 编译运行C语言程序代码的方法...

CFree是一款C语言编译软件&#xff0c;用户可以利用这款软件编译C/C程序 &#xff0c;如果你想要运行已经编写好的C语言代码&#xff0c;只需要几个简单的操作即可实现&#xff0c;如果你还不知道怎么运行&#xff0c;就赶快来看看下面的教程吧&#xff01;1、首先需要先进入到…

docker4dotnet #2 容器化主机

.NET 猿自从认识了小鲸鱼&#xff0c;感觉功力大增。上篇 《docker4dotnet #1 前世今生 & 世界你好》中给大家介绍了如何在Windows上面配置Docker for Windows和Docker Tools for Visual Studio来使用docker协助.NET Core应用的开发&#xff0c;这篇我们来看看如何创建和管…

Java GC系列(2):Java垃圾回收是如何工作的

转载自 Java GC系列&#xff08;2&#xff09;&#xff1a;Java垃圾回收是如何工作的本教程是为了理解基本的Java垃圾回收以及它是如何工作的。这是垃圾回收教程系列的第二部分。希望你已经读过了第一部分&#xff1a;《Java 垃圾回收介绍》。 Java 垃圾回收是一项自动化的过…

c语言程序为什么运行一半就自动关闭了,C语言为什么程序运行一半就出现停止工作...

匿名用户1级2016-04-04 回答有点儿意思。原因却出乎意料的简单。 char *rwtab[27]{"main","if","then","while","do"," static","int"," double","struct","break",&quo…

docker4dotnet #1 – 前世今生 amp; 世界你好

作为一名.NET Developer&#xff0c;这几年看着docker的流行实在是有些眼馋。可惜的是&#xff0c;Docker是基于Linux环境的&#xff0c;眼瞧着那些 java, python, node.js, go 甚至连php程序员都可以docker了&#xff0c;自己还在苦哈哈的装虚拟机&#xff0c;实在是急啊&…

Java GC系列(3):垃圾回收器种类

转载自 Java GC系列&#xff08;3&#xff09;&#xff1a;垃圾回收器种类在这篇教程中我们将学习几种现有的垃圾回收器。在Java中&#xff0c;垃圾回收是一个自动的进程可以替代程序员进行内存的分配与回收这些复杂的工作。这篇是垃圾回 收教程系列的第三篇&#xff0c;在前面…

当当网新用户注册界面——CSS代码

<strong><span style"font-size:32px;color:#ff9966;">所有用到的图片都已上传&#xff0c;请在<a target_blank href"http://download.csdn.net/detail/qq_34137397/9667142">这里</a>下载</span></strong> <pre …

计算机二级c语言考试模拟试题,计算机二级C语言考前模拟试题及答案2016

计算机二级C语言考前模拟试题及答案2016(1)有以下程序&#xff1a;程序运行后的输出结果是(   )。A.852B.963C.741D.875421(2)有以下程序&#xff1a;程序运行后的输出结果是(   )。A.let4B.m2C.m6D.m5(3)有以下程序&#xff1a;程序运行后的输出结果是(   )。A.6B.3C.8D…

Visual Studio Code 1.3终于增加了标签页

2016年6月发布的Visual Studio Code 1.3版更新已发布&#xff0c;该版本提供了用户呼声最高的一个功能请求。 很长一段时间来&#xff0c;开发者一直呼吁为Microsoft的跨平台代码编辑器提供标签页功能。在UserVoice网站上有关这个功能的请求已获得超过9,000个投票。 标签页默认…

lego ev3 c语言编程,乐高 EV3 高级编程 – 第一课:安装

我的学生写的教程&#xff0c;英文版的&#xff0c;好吧&#xff0c;我翻译一下&#xff01;先介绍一下我的学生&#xff0c;今年 12 岁 (2018年)&#xff0c;普通 2 等中学初中 2 年级(学校名字就不说了&#xff0c;说了你也没听过&#xff01;)&#xff0c;除了数学和科学比较…

Java GC系列(4):垃圾回收监视和分析

转载自 Java GC系列&#xff08;4&#xff09;&#xff1a;垃圾回收监视和分析在这个Java GC系列教程中&#xff0c;让我们学习用于垃圾回收监视和分析的工具。然后&#xff0c;选用一种工具来监视一个Java示例程序的垃圾回收过程。如果你是一名初学者&#xff0c;你最好仔细阅…

ASP.NET Core开发-使用Nancy框架

Nancy简介 Nancy是一个轻量级的独立的框架&#xff0c;下面是官网的一些介绍: Nancy 是一个轻量级用于构建基于 HTTP 的 Web 服务&#xff0c;基于 .NET 和 Mono 平台&#xff0c;框架的目标是保持尽可能多的方式&#xff0c;并提供一个super-duper-happy-path所有交互。Nancy …