Buffer

  • ByteBuffer byteBuffer;
  • CharBuffer charBuffer;
  • ShortBuffer shortBuffer;
  • IntBuffer intBuffer;
  • LongBuffer longBuffer;
  • FloatBuffer floatBuffer;
  • DoubleBuffer doubleBuffer;

    1. String data = "hellonio";
    2. // 创建 1024是缓冲区大小
    3. ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
    4. //元素放进去
    5. byteBuffer.put(data.getBytes());
    6. byteBuffer.flip();//切换模式 读/写
    7. byteBuffer.limit(); //写模式下是能写多少数据数据 读模式下是能读的数据长度大小
    8. byteBuffer.position();//写模式下是写的位置 读模式下是读的内容下标 默认从0开始读
    9. byteBuffer.capacity();//读写模式下都是缓冲区容量
    10. //把读取的数据放到buff中 读取0-3的数据
    11. byte[] buff = new byte[limit];
    12. byteBuffer.get(buff, 0, 3);

    Channel

    常规拷贝文件

    • 系统内核读取文件存放到内存中,然后用户进程去内核内存中,复制系统读取到的内容这才完成文件拷贝。

      直接内存拷贝

    • 用户和内核共享一块内存这样就避免了二次操作

    • 一般用于拷贝大文件

      1. public static void t1() throws Exception {
      2. FileInputStream fis = new FileInputStream("f:/1.txt");
      3. FileOutputStream fos = new FileOutputStream("f:/121.txt");
      4. FileChannel inChannel = fis.getChannel();
      5. FileChannel outChannel = fos.getChannel();
      6. ByteBuffer buff = ByteBuffer.allocate(1024);
      7. while (inChannel.read(buff) != -1) {
      8. // 切换读模式
      9. buff.flip();
      10. outChannel.write(buff);
      11. buff.clear();
      12. }
      13. outChannel.close();
      14. inChannel.close();
      15. fos.close();
      16. fis.close();
      17. }

      内存映射文件拷贝

      1. //读 把153M的文件装载到内存中花费87毫秒
      2. public static void t2() throws Exception {
      3. FileInputStream fis = new FileInputStream("f:/20200604_164622.mp4");
      4. FileChannel inChannel = fis.getChannel();//NIO的通道
      5. // 内存映射 读 申请空间0-文件大小
      6. MappedByteBuffer mappedByteBuffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
      7. long fileLen = inChannel.size();//文件大小
      8. byte[] buff = new byte[(int) fileLen];//文件大小的数组
      9. long start = System.currentTimeMillis();
      10. mappedByteBuffer.get(buff);
      11. long end = System.currentTimeMillis();
      12. System.out.println("use time = " + (end - start));
      13. }
  • 缺点不好控制机器上的内存消耗有风险

    通道传输

  • 需要系统支持,如果不支持就采用内存映射的方式传输 ```java //拷贝花费104毫秒 public static void t4() throws Exception { //开辟通道 FileChannel inChannel = FileChannel.open(Paths.get(“f:/20200604164622.mp4”), StandardOpenOption.READ); FileChannel outChannel = FileChannel.open(Paths.get(“f:/20200604_164622.mp4”)

    1. , StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE);

    long start = System.currentTimeMillis(); // transferToDirectly // transferToTrustedChannel // transferToArbitraryChannel //读取的文件传到通道里面去 inChannel.transferTo(0, inChannel.size(), outChannel); long end = System.currentTimeMillis(); System.out.println(“use time = “ + (end - start)); inChannel.close(); outChannel.close();

}

  1. <a name="Gk3MF"></a>
  2. ### 分散和聚集
  3. ```java
  4. public static void t5() throws Exception {
  5. FileInputStream fis = new FileInputStream("f:/1.txt");
  6. FileChannel inChannel = fis.getChannel();
  7. //创建缓冲区
  8. ByteBuffer header = ByteBuffer.allocate(5);
  9. ByteBuffer body = ByteBuffer.allocate(10);
  10. // 12345678901234567890
  11. // header = 12345
  12. // body = 6789012345
  13. ByteBuffer[] arr = {header, body};
  14. inChannel.read(arr);
  15. // 切换读模式
  16. //循环读取 先读取5个字节 在读取10个字节一共15个没有读取到的内容就没读取到
  17. for (ByteBuffer bb : arr) {
  18. bb.flip();
  19. System.out.println(new String(bb.array(), 0, bb.limit()));
  20. }
  21. //写入
  22. FileOutputStream fos = new FileOutputStream("f:/111222.txt");
  23. FileChannel outChannel = fos.getChannel();
  24. outChannel.write(arr);
  25. outChannel.close();
  26. }

截断

  1. //直接把原内容截了截取了7个
  2. public static void t6() throws Exception {
  3. FileOutputStream fos = new FileOutputStream("f:/111222.txt", true);
  4. FileChannel outChannel = fos.getChannel();
  5. outChannel.truncate(7);
  6. }

加锁

FileLock对当前文件加锁解决多线程问题