zoukankan      html  css  js  c++  java
  • Android开发进阶之NIO非阻塞包(二)

    有关Android NIO我们主要分为三大类,ByteBufferFileChannelSocketChannel。由于篇幅原因今天Android123只对前两个做说明。NIO和传统的I/O比较大的区别在于传输方式非阻塞,一种基于事件驱动的模式,将会使方法执行完后立即返回,传统I/O主要使用了流Stream的方式,而在New I/O中,使用了字节缓存ByteBuffer来承载数据。

       ByteBuffer位于java.nio包中,目前提供了Java基本类型中除Boolean外其他类型的缓冲类型,比如ByteBufferDoubleBufferFloatBufferIntBufferLongBufferShortBuffer  。同时还提供了一种更特殊的映射字节缓冲类型MappedByteBuffer。在传统IO的输入输出流中,InputStream中只提供了字节型或字节数组的访问对应NIO就是ByteBuffer,但是处理传统的DataInputStreamint等类型,就是IntBuffer,但是缓冲类型并没有提供UTF这样的类型处理,所以我们仍然需要使用ByteBuffer处理字符串,但是NIO提供了一个封装的类在java.nio.charset包中,通过字符的编码CharsetEncoder和解码CharsetDecoder类来处理字符串,同时这些类可以方便转换编码比如GBKUTF等等。

      一、ByteBuffer

      1) 实例化

      直接使用ByteBuffer类的静态方法static ByteBuffer allocate(int capacity) static ByteBuffer allocateDirect(int capacity)  这两个方法来分配内存空间,两种方法的区别主要是后者更适用于繁复分配的字节数组。而 put(ByteBuffer src) 可以从另一个ByteBuffer中构造,也可以通过wrap方法从byte[]中构造,具体参考下面的类型转化内容。

      2) 类型转化

       ByteBuffer可以很好的和字节数组byte[]转换类型,通过执行ByteBuffer类的final byte[]  array() 方法就可以将ByteBuffer转为byte[]。从byte[]来构造ByteBuffer可以使用wrap方法,目前Android或者说Java提供了两种重写方法,比如为static ByteBuffer  wrap(byte[] array)  static ByteBuffer  wrap(byte[] array, int start, int len)  ,第二个重载方法中第二个参数为从array这个字节数组的起初位置,第三个参数为array这个字节数组的长度。

      3) ByteBuffer中添加元素

      目前ByteBuffer提供了多种put重写类型来添加,比如put(byte b) putChar(char value) putFloat(float value) 等等,需要注意的是,按照Java的类型长度,一个byte1字节,一个char类型是2字节,一个floatint4字节,一个long则为8字节,和传统的C++有些区别。所以内部的相关位置也会发生变化,同时每种方法还提供了定位的方法比如ByteBuffer  put(int index, byte b) 

      4) ByteBuffer中获取元素

      同上面的添加想法,各种put被换成了get,比如byte  get()  float  getFloat()  ,当然了还提供了一种定位的方式,比如double  getDouble(int index) 

      5) ByteBuffer中字节顺序

      对于Java来说默认使用了BIG_ENDIAN方式存储,和C正好相反的,通过

      final ByteOrder  order() 返回当前的字节顺序。

      final ByteBuffer  order(ByteOrder byteOrder)  设置字节顺序,ByteOrder类的值有两个定义,比如LITTLE_ENDIANBIG_ENDIAN,如果使用当前平台则为ByteOrder.nativeOrder()Android中则为 BIG_ENDIAN,当然如果设置为order(null) 则使用LITTLE_ENDIAN

      二、FileChannel

       NIO中除了Socket外,还提供了File设备的通道类,FileChannel位于java.nio.channels.FileChannel包中,在Android SDK文档中我们可以方便的找到,对于文件复制我们可以使用ByteBuffer方式作为缓冲,比如

      String infile = "/sdcard/cwj.dat";
      String outfile = "/sdcard/android123-test.dat";

        FileInputStream fin = new FileInputStream( infile );
        FileOutputStream fout = new FileOutputStream( outfile );

        FileChannel fcin = fin.getChannel();
        FileChannel fcout = fout.getChannel();

        ByteBuffer buffer = ByteBuffer.allocate( 1024 ); //分配1KB作为缓冲区

        while (true) {
        buffer.clear(); //
    每次使用必须置空缓冲区

          int r = fcin.read( buffer );

          if (r==-1) {
            break;
          }

       buffer.flip(); //写入前使用flip这个方法

          fcout.write( buffer );
        }

       flipclear这两个方法是java.nio.Buffer包中,ByteBuffer的父类是从Buffer类继承而来的,这点Android123要提醒大家看Android SDK文档时注意Inherited Methods,而JDK的文档就比较直接了,同时复制文件使用FileChanneltransferTo(long position, long count, WritableByteChannel target) 这个方法可以快速的复制文件,无需自己管理ByteBuffer缓冲区。明天Android开发网介绍NIO主要的Socket相关的内容。

     

  • 相关阅读:
    Github精选——devops一体化监控平台工具WGCLOUD
    [搬运][中英双语]字体推荐 | 如果你每天都在代码面前,为何不让其变得有趣起来呢?
    【学习笔记】二分图最大匹配 -- 从网络流到匈牙利算法
    【详细揭秘】多重集の交错排列
    支配树口胡
    题解 洛谷 P2388 阶乘之乘
    [eJOI2019]异或橙子 题解
    VBA (Excel) 插入多行的方法 & 算法对比
    20000套免费ppt模板获取攻略
    包你扫到敬业福,集五福活动,福字大全
  • 原文地址:https://www.cnblogs.com/cpcpc/p/2123008.html
Copyright © 2011-2022 走看看