今天,讲讲android内byteBuffer的使用。

缓冲区(Buffer)就是在内存中预留指定大小的存储空间用来对输入/输出(I/O)的数据作临时存储,这部分预留的内存空间就叫做缓冲区:

使用缓冲区有这么两个好处:

1、减少实际的物理读写次数

2、缓冲区在创建时就被分配内存,这块内存区域一直被重用,可以减少动态分配和回收内存的次数

举个简单的例子,比如A地有1w块砖要搬到B地

由于没有工具(缓冲区),我们一次只能搬一本,那么就要搬1w次(实际读写次数)

如果A,B两地距离很远的话(IO性能消耗),那么性能消耗将会很大

但是要是此时我们有辆大卡车(缓冲区),一次可运5000本,那么2次就够了

相比之前,性能肯定是大大提高了。

而且一般在实际过程中,我们一般是先将文件读入内存,再从内存写出到别的地方

这样在输入输出过程中我们都可以用缓存来提升IO性能。

所以,buffer在IO中很重要。在旧I/O类库中(相对Java.nio包)中的BufferedInputStream、BufferedOutputStream、BufferedReader和BufferedWriter在其实现中都运用了缓冲区。java.nio包公开了Buffer API,使得Java程序可以直接控制和运用缓冲区。

在Java NIO中,缓冲区的作用也是用来临时存储数据,可以理解为是I/O操作中数据的中转站。缓冲区直接为通道(Channel)服务,写入数据到通道或从通道读取数据,这样的操利用缓冲区数据来传递就可以达到对数据高效处理的目的。在NIO中主要有八种缓冲区类(其中MappedByteBuffer是专门用于内存映射的一种ByteBuffer):

现在讲讲具体的使用

1.创建ByteBuffer
1.1 使用allocate()静态方法
    ByteBuffer buffer=ByteBuffer.allocate(256);
    以上方法将创建一个容量为256字节的ByteBuffer,如果发现创建的缓冲区容量太小,唯一的选择就是重新创建一个大小合适的缓冲区.

1.2 通过包装一个已有的数组来创建
    如下,通过包装的方法创建的缓冲区保留了被包装数组内保存的数据.
    ByteBuffer buffer=ByteBuffer.wrap(byteArray);

如果要将一个字符串存入ByteBuffer,可以如下操作:
    String sendString="你好,服务器. ";
    ByteBuffer sendBuffer=ByteBuffer.wrap(sendString.getBytes("UTF-16"));

2.回绕缓冲区
  buffer.flip();
  这个方法用来将缓冲区准备为数据传出状态,执行以上方法后,输出通道会从数据的开头而不是末尾开始.回绕保持缓冲区中的数据不变,只是准备写入而不是读取.

3.清除缓冲区
  buffer.clear();
  这个方法实际上也不会改变缓冲区的数据,而只是简单的重置了缓冲区的主要索引值.不必为了每次读写都创建新的缓冲区,那样做会降低性能.相反,要重用现在的缓冲区,在再次读取之前要清除缓冲区.

4.从套接字通道(信道)读取数据
  int bytesReaded=socketChannel.read(buffer);
  执行以上方法后,通道会从socket读取的数据填充此缓冲区,它返回成功读取并存储在缓冲区的字节数.在默认情况下,这至少会读取一个字节,或者返回-1指示数据结束.

5.向套接字通道(信道)写入数据
  socketChannel.write(buffer);
  此方法以一个ByteBuffer为参数,试图将该缓冲区中剩余的字节写入信道.

-----------------------

ByteBuffer俗称缓冲器, 是将数据移进移出通道的唯一方式,并且我们只能创建一个独立的基本类型缓冲器,或者使用“as”方法从 ByteBuffer 中获得。ByteBuffer 中存放的是字节,如果要将它们转换成字符串则需要使用 Charset , Charset 是字符编码,它提供了把字节流转换成字符串 ( 解码 ) 和将字符串转换成字节流 ( 编码) 的方法。

private byte[] getBytes (char[] chars) {//将字符转为字节(编码)
   Charset cs = Charset.forName ("UTF-8");
   CharBuffer cb = CharBuffer.allocate (chars.length);
   cb.put (chars);
   cb.flip ();
   ByteBuffer bb = cs.encode (cb)
   return bb.array();
         }

private char[] getChars (byte[] bytes) {//将字节转为字符(解码)
      Charset cs = Charset.forName ("UTF-8");
      ByteBuffer bb = ByteBuffer.allocate (bytes.length);
      bb.put (bytes);
      bb.flip ();
       CharBuffer cb = cs.decode (bb);
  
   return cb.array();
}

通道也就是FileChannel,可以由FileInputStream,FileOutputStream,RandomAccessFile三个类来产生,例如:FileChannel fc = new FileInputStream().getChannel();与通道交互的一般方式就是使用缓冲器,可以把通道比如为煤矿(数据区),而把缓冲器比如为运煤车,想要得到煤一般都通过运煤车来获取,而不是直接和煤矿取煤。用户想得到数据需要经过几个步骤:

一、用户与ByteBuffer的交互

向ByteBuffer中输入数据,有两种方式但都必须先为ByteBuffer指定容量

ByteBuffer buff = ByteBuffer.allocate(BSIZE);

a)  buff  =  ByteBuffer.wrap("askjfasjkf".getBytes())注意:wrap方法是静态函数且只能接收byte类型的数据,任何其他类型的数据想通过这种方式传递,需要进行类型的转换。

b)  buff.put();可以根据数据类型做相应调整,如buff.putChar(chars),buff.putDouble(double)等

二、FileChannel 与 ByteBuffer的交互:

缓冲器向通道输入数据

FileChannel fc = new FileInputStream().getChannel();

fc.write(buff);

fc.close();

三、 用户与ByteBuffer交互

通道向缓冲器送入数据

FileChannel fc =  new FileOutputStream().getChannel();

fc.read( buff);

fc.flip();

四、呈现给用户(三种方式)

1)String encoding = System.getProperty("file.encoding");

System.out.println("Decoded using " + encoding + ": "  + Charset.forName(encoding).decode(buff));

2)System.out.println(buff.asCharBuffer());//这种输出时,需要在输入时就进行编码getBytes("UTF-8")

3) System.out.println(buff.asCharBuffer());//通过CharBuffer向ByteBuffer输入 buff.asCharBuffer().put。

fc.rewind();

android byteBuffer的使用就讲完了。

就这么简单。



android byteBuffer的使用相关推荐

  1. android ByteBuffer.allocateDirect()造成OutOfMemoryError

    最近用一个开源的控件,碰到ByteBuffer.allocateDirect()的时候OutOfMemoryError的问题,偶尔调用没问题,如果频繁的调用这个控件就会发生OutOfMemoryErr ...

  2. android bytebuffer 大小,ByteBuffer小结

    前言 在阅读源码的过程中,发现比较多的使用到了bytebuffer,但是由于之前没有接触过,所以现做以总结,以备复习. ByteBuffer类位于java.nio包下,所谓nio:代表new io,另 ...

  3. 【Flutter】Flutter 混合开发 ( Flutter 与 Native 通信 | Android 端实现 BasicMessageChannel 通信 )

    文章目录 前言 一.Android 端 BasicMessageChannel 构造函数 二.Android 端 MessageCodec 子类实现 三.Android 端 setMessageHan ...

  4. Android坑点-ByteBuffer.array() 入过坑吗

    目录 1.坑点介绍 2.正确使用姿势(入坑了怎么办) 3.坑坑详解 3.1HeapByteBuffer可以用buffer.array() 3.2DirectByteBuffer的坑在哪里 1.坑点介绍 ...

  5. Android OpenGL ES(十一)绘制一个20面体 .

    前面介绍了OpenGL ES所有能够绘制的基本图形,点,线段和三角形.其它所有复杂的2D或3D图形都是由这些基本图形构成. 本例介绍如何使用三角形构造一个正20面体.一个正20面体,有12个顶点,20 ...

  6. Android OpenGL使用GLSurfaceView预览视频

    Android OpenGL使用GLSurfaceView预览视频 第一章 相关知识介绍 在介绍具体的功能之前,先对一些主要的类和方法进行一些介绍,这样可以更好的理解整个程序 1.1 GLSurfac ...

  7. android jni 调用 java_Android与JNI(二) ---- Java调用C++ 动态调用

    目录: 1. 简介 2. JNI 组件的入口函数 3. 使用 registerNativeMethods 方法 4. 测试 5. JNI 帮助方法 6. 参考资料 1. 简介 Android与JNI( ...

  8. android 获取视频大小,Android 获取视频缩略图(获取视频每帧数据)的优化方案

    速度对比 左边的图片是通过方式1 右边的图片是通过方式2 speed.gif 速度优化,效果拔群. 在缩小2倍的Bitmap输出情况下 使用MediaMetadataRetriever 抽帧的速度,每 ...

  9. wifi boombox android,android filament入门,GLB和GLTF模型查看器

    filament入门挺难的,主要是因为受干扰的信息太多了,有arCore的干扰,也有scenceform的干扰.这里通过制作3D模型查看器的方式,理清他们之间的关系. 有用的信息来源主要有3个: 1, ...

最新文章

  1. 新都一职高计算机学什么,新都第一职业高中怎么样
  2. AI视觉组仙人一步之模型调优
  3. 举例说明html语言的结构,HTML语言的结构
  4. 界面 高炉系统_浅议工业互联网与传统计算机系统的关系
  5. android简单的计算器
  6. oracle之 RA-00054: resource busy and acquire with NOWAIT specified or timeout expired
  7. jdbc增删改查_JDBC第二期
  8. Linux 终端环境安装 L2TP 客户端
  9. 如何构建基于.NET Core和云环境下的微服务技术体系?
  10. 阿里巴巴又一开源项目被列入 CNCF 云原生全景图
  11. 解决windows7“您可能没有权限使用网络资源”的方法
  12. 互联网诞生记: 浪成于微澜之间
  13. php多线程采集,php浏览器模拟:用于多线程处理的curl_multi一族函数使用介绍
  14. Linux下删除特殊字符的文件或文件夹
  15. 关于c#:如何续订过期的ClickOnce证书?
  16. 嵌入式开发和c/c++编程经验总结
  17. 巴西本地支付PagSeguro
  18. 对于有些网站无法打开F12或者firebug的现象解答
  19. Flink中Trigger的介绍及使用
  20. CTFSHOW大赛原题篇(web726-web740)

热门文章

  1. Xcode error: conflicting types for 'XXXX'
  2. php绝对路径与相对路径之间关系的的深入研究
  3. t-sql导出EXCEL语句
  4. 2006年软件500强
  5. [原创]浅谈在创业公司对PMF的理解
  6. Linux - XShell - alt 快捷键的设置
  7. scrapy爬取京东
  8. PXE 01-PXE介绍
  9. 2015 Google code jam Qualification Round A 水
  10. linux 酷炫的命令行