ByteBuffer方法演示

288 阅读2分钟
分配内存
public static void main(String[] args) {
    ByteBuffer byteBuffer = ByteBuffer.allocate(10);
    ByteBuffer buffer = ByteBuffer.allocateDirect(10);

    System.out.println("allocate 分配堆内存 " + byteBuffer.getClass());
    System.out.println("allocateDirect 分配直接内存" +  buffer.getClass());
}

sdout

  • allocate 分配的内存 class java.nio.HeapByteBuffer
  • allocateDirect 分配直接内存class java.nio.DirectByteBuffer

区别 :

  • HeapByteBuffer : Java堆内存为缓冲区分配空间,读写效率较低,受到 GC对数据搬迁的影响
  • DirectByteBuffer:直接内存分配,读写效率高。分配效率低 因为是系统内存么,要调用操作系统的函数,分配效率低,这时候注意没有了 GC , 我们要手动进行回收,使用不当会造成内存泄漏!!

向buffer 写入数据

  • channel 的 read 方法
  • buffer 自己的 put 方法。

从 buffer 读取数据

  • channel 的 write 方法。

  • buffer 的 get 方法。

  • 读取重复内容

    • rewind 方法 将 position 重新置为0
    • 调用 get(idx) 方法 获取 idx 的内容,不会移动读指针。
  • rewind 方法的增强,markreset 方法 , mark 标记读取位置,reset使得 position 回指mark。 类似 备忘录hh。

字符串 转 ByteBuffer

public class ByteBufferString {
    public static void main(String[] args) {
        byte[] bytes = "hello".getBytes();
        ByteBuffer allocate = ByteBuffer.allocate(10);
        allocate.put(bytes);
        debugAll(allocate);

        // CharSet 类 defaultCharset : 使用当前操作系统的字符集
        Charset charset = Charset.defaultCharset();
        ByteBuffer encode = charset.encode("hello");
        debugAll(encode);
    }
}

或者使用 指定字符集转换 ByteBuffer

image.png

结果示例均为下图所示

image.png

ByteBuffer 转为 其他buffer 或者字符串

public static void main(String[] args) {
    ByteBuffer wrap = ByteBuffer.wrap(bytes);
    debugAll(wrap);
    System.out.println(new String(wrap.array()));
}

image.png

前者直接返回 byte数组 ,并不是真正的读取根据视频讲解而知 这里有个缺陷,如果使用 decode 他在写模式下是不会显示byteBuffer 转为字符串的内容的,只有在读模式下才可以。建议使用此方式读取(个人认为这样数据会安全一点),试想,谁在写的时候读啊,而且也不如 后者方便

建议转换方式。
public class ByteBufferString {
    public static void main(String[] args) {
        byte[] bytes = "hello".getBytes();

        // CharSet 类 defaultCharset : 使用当前操作系统的字符集
        Charset charset = Charset.defaultCharset();
            ByteBuffer wrap = ByteBuffer.wrap(bytes);
            debugAll(wrap);
            System.out.println( "指定字符集形式" + StandardCharsets.UTF_8.decode(wrap));
            debugAll(wrap);
            System.out.println("charset 形式 " + charset.decode(wrap));
    }
}

值得注意的是 在执行 encode 方法之后 position 会到达 limit 读的位置

ByteBuffer 分散读 集中写

GatheringWrites

public class TestGatheringWrites {
    public static void main(String[] args) {
        ByteBuffer hello = StandardCharsets.UTF_8.encode("hello");  // 10bit
        ByteBuffer world = StandardCharsets.UTF_8.encode("world"); // 10 bit
        ByteBuffer b3 = StandardCharsets.UTF_8.encode("===你好世界"); // 18bit
        try (FileChannel w = new RandomAccessFile("words.txt", "rw").getChannel()) {
            w.write(new ByteBuffer[]{hello,world,b3});
        } catch (IOException e) {
        }
    }
}
Scattering Reads 分散读
public class TestScatteringReads {
   public static void main(String[] args) {
       String  s = (String) System.getProperties().get("user.dir");
       System.out.println(s);
       try (FileChannel channel = new RandomAccessFile(s + "/words.txt", "r").getChannel()) {
           ByteBuffer buffer = ByteBuffer.allocate(3);
           ByteBuffer buffer1 = ByteBuffer.allocate(3);
           ByteBuffer buffer2 = ByteBuffer.allocate(5);
           channel.read(new ByteBuffer[]{buffer, buffer1, buffer2});
           buffer.flip();
           buffer1.flip();
           buffer2.flip();
           debugAll(buffer);
           debugAll(buffer1);
           debugAll(buffer2);
       } catch (IOException e) {
       }
   }

}

image.png

好文集锦

NIO基础

**注意点 : RandomAccessFile 构造函数的mode模式值只有 r , rw , rws ,rwd 。 且这里的rw写会覆盖**

IllegalArgumentException – if the mode argument is not equal to one of "r", "rw", "rws", or "rwd"

这里感觉可以做文件合并