分配内存
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方法的增强,mark加reset方法 ,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
结果示例均为下图所示
ByteBuffer 转为 其他buffer 或者字符串
public static void main(String[] args) {
ByteBuffer wrap = ByteBuffer.wrap(bytes);
debugAll(wrap);
System.out.println(new String(wrap.array()));
}
前者直接返回 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) {
}
}
}
好文集锦
**注意点 : RandomAccessFile 构造函数的mode模式值只有 r , rw , rws ,rwd 。 且这里的rw写会覆盖**
IllegalArgumentException – if the mode argument is not equal to one of "r", "rw", "rws", or "rwd"
这里感觉可以做文件合并