Java NIO 通道(Channel) 学习笔记

本是古典 何须时尚 2022-05-09 14:06 300阅读 0赞

一、通道(Channel):用于源节点与目标节点的连接。在 Java NIO 中负责缓冲区中数据的传输。Channel 本身不存储数据,因此需要配合缓冲区进行传输。

二、通道的主要实现类
java.nio.channels.Channel 接口:
|—FileChannel
|—SocketChannel
|—ServerSocketChannel
|—DatagramChannel

三、获取通道

  1. Java 针对支持通道的类提供了 getChannel() 方法

    1. 本地 IO
    2. FileInputStream/FileOutputStream
    3. RandomAccessFile
    4. 网络IO
    5. Socket
    6. ServerSocket
    7. DatagramSocket
  2. 在 JDK 1.7 中的 NIO.2 针对各个通道提供了静态方法 open()

  3. 在 JDK 1.7 中的 NIO.2 的 Files 工具类的 newByteChannel()

    四、通道之间的数据传输
    transferFrom()
    transferTo()

    五、分散(Scatter)与聚集(Gather)
    分散读取(Scattering Reads):将通道中的数据分散到多个缓冲区中
    聚集写入(Gathering Writes):将多个缓冲区中的数据聚集到通道中

    六、字符集:Charset
    编码:字符串 -> 字节数组
    解码:字节数组 -> 字符串

Channel代码实例:利用通道完成文件的复制

1.非直接缓冲区

  1. //利用通道完成文件的复制(非直接缓冲区)
  2. @Test
  3. public void testChannel(){
  4. long start = System.currentTimeMillis();
  5. FileInputStream fis = null;
  6. FileOutputStream fos = null;
  7. //1. 获取通道
  8. FileChannel inChannel = null;
  9. FileChannel outChannel = null;
  10. try{
  11. fis = new FileInputStream("G:/MP4/00.mp4");
  12. fos = new FileOutputStream("G:/MP4/01.mp4");
  13. inChannel = fis.getChannel();
  14. outChannel = fos.getChannel();
  15. //2. 分配指定大小的非直接缓冲区
  16. ByteBuffer buff = ByteBuffer.allocate(1024);
  17. //3. 将通道中的数据存入缓冲区中
  18. while(inChannel.read(buff) != -1){
  19. buff.flip(); //切换读取数据的模式
  20. //4.将缓冲区中的数据写入通道中
  21. outChannel.write(buff);
  22. buff.clear(); //清空缓冲区
  23. }
  24. }catch(IOException e){
  25. e.printStackTrace();
  26. }finally{
  27. if(fis != null){
  28. try {
  29. fis.close();
  30. } catch (IOException e) {
  31. e.printStackTrace();
  32. }
  33. }
  34. if(fos != null){
  35. try {
  36. fos.close();
  37. } catch (IOException e) {
  38. e.printStackTrace();
  39. }
  40. }
  41. if(inChannel != null){
  42. try {
  43. inChannel.close();
  44. } catch (IOException e) {
  45. e.printStackTrace();
  46. }
  47. }
  48. if(outChannel != null){
  49. try {
  50. outChannel.close();
  51. } catch (IOException e) {
  52. e.printStackTrace();
  53. }
  54. }
  55. }
  56. long end = System.currentTimeMillis();
  57. System.out.println("耗费时间为:" + (end - start));
  58. }

2.直接缓冲区

  1. @Test
  2. public void testFileChannel(){
  3. long start = System.currentTimeMillis();
  4. try {
  5. FileChannel inChannel = FileChannel.open(Paths.get("G:/MP4/00.mp4"), StandardOpenOption.READ);
  6. FileChannel outChannel = FileChannel.open(Paths.get("G:/MP4/04.mp4"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);
  7. // start 1.第一种实现方式:使用直接缓冲区完成文件的复制(内存映射文件)
  8. MappedByteBuffer inMappedBuf = inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());
  9. MappedByteBuffer outMappedBuf = outChannel.map(MapMode.READ_WRITE, 0, inChannel.size());
  10. //直接对缓冲区进行数据的读写操作
  11. byte[] dst = new byte[inMappedBuf.limit()];
  12. inMappedBuf.get(dst);
  13. outMappedBuf.put(dst);
  14. // end 1.第一种实现方式:使用直接缓冲区完成文件的复制(内存映射文件)
  15. // start 2.第二种实现方式:通道之间的数据传输(直接缓冲区) transferTo || transferFrom
  16. inChannel.transferTo(0, inChannel.size(), outChannel);
  17. // outChannel.transferFrom(inChannel, 0, inChannel.size());
  18. // end 2.第二种实现方式:通道之间的数据传输(直接缓冲区) transferTo || transferFrom
  19. inChannel.close();
  20. outChannel.close();
  21. long end = System.currentTimeMillis();
  22. System.out.println("耗费时间为:" + (end - start));
  23. } catch (IOException e) {
  24. e.printStackTrace();
  25. }
  26. }

发表评论

表情:
评论列表 (有 0 条评论,300人围观)

还没有评论,来说两句吧...

相关阅读