Java NIO之通道Channel代码实例

喜欢ヅ旅行 2023-06-10 11:29 85阅读 0赞

文章目录

    • 代码实例
    • 控制台输出结果

相关Java NIO详解: Java NIO详解

代码实例

  1. import java.io.*;
  2. import java.nio.ByteBuffer;
  3. import java.nio.MappedByteBuffer;
  4. import java.nio.channels.FileChannel;
  5. import java.nio.file.Paths;
  6. import java.nio.file.StandardOpenOption;
  7. import java.util.concurrent.ExecutorService;
  8. import java.util.concurrent.Executors;
  9. /** * 通道channel: * 用于源节点与目标节点的连接,本身不负责存储数据,主要是配合缓冲区,负责数据的运输。 * 1.主要的实现类: * java.nio.channels.Channel接口 * --用于本地文件: * -FileChannel * --用于网络 * -SocketChannel一般用于客户端,TCP协议 * -ServerSocketChannel一般用于服务端,TCP协议 * -DatagramChannel基于UDP协议,主要用于发送和接收数据包 * 2.获取通道Channel的方法 * (1)java针对支持通道的类提供了getChannel()方法 * --本地文件 * FileInputStream/FileOutoutStream * RandomAccessFile * --网络传输 * Socket * ServerSocket * DatagramSocket * (2)在JDK1.7中的NIO2针对各个通道提供了静态方法open() * (3)在JDK1.7中的NIO2中Files工具类newByteChannel() * 3.通道之间的传输,两种方法 * transferForm() * transferTo() * */
  10. public class ChannelDome {
  11. /** * main测试,利用线程池进行创建线程并运行。 */
  12. public static void main(String[] args) {
  13. //1.创建可重用固定线程数量的线程池
  14. ExecutorService executorService= Executors.newFixedThreadPool(10);
  15. //System.out.println(executorService.getClass());//查看调用了那个接口的对应实现类。
  16. //2.执行指定的线程的操作,需要提供的是Runnable接口或Callable接口实现类的对象
  17. copyFileThread1 thread1=new copyFileThread1();
  18. copyFileThread2 thread2=new copyFileThread2();
  19. channelWriteAndRead thread3=new channelWriteAndRead();
  20. channelTransfer thread4=new channelTransfer();
  21. executorService.execute(thread1);
  22. executorService.execute(thread2);
  23. executorService.execute(thread3);
  24. executorService.execute(thread4);
  25. //executorService.submit();
  26. executorService.shutdown();
  27. }
  28. /** * 1.利用通道进行本地文件的复制功能(非直接缓冲区) * @param copyFrom * @param copyTo * @return boolean */
  29. public boolean copyFileByChannel(String copyFrom,String copyTo) throws IOException {
  30. long start=System.currentTimeMillis();
  31. boolean result=false;
  32. FileInputStream inputStream=null;
  33. FileOutputStream outputStream=null;
  34. FileChannel inputChannel=null;
  35. FileChannel outputChannel=null;
  36. try {
  37. //1.获取本地输入输出流
  38. inputStream = new FileInputStream(copyFrom);
  39. outputStream = new FileOutputStream(copyTo);
  40. //2.获取本地对应输入输出通道
  41. inputChannel = inputStream.getChannel();
  42. outputChannel = outputStream.getChannel();
  43. //3.分配指定大小的缓冲区
  44. ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
  45. //4.将输入通道中的数据存入缓冲区
  46. while (inputChannel.read(byteBuffer) != -1) { //从当前通道position读取数据到缓冲区,若到达末尾,返回-1
  47. byteBuffer.flip();//切换到读取数据模式
  48. //5.将缓冲区的数据写入到输出通道中
  49. outputChannel.write(byteBuffer);
  50. byteBuffer.clear();//清空缓冲区
  51. result=true;
  52. }
  53. }finally {
  54. if(inputStream !=null){
  55. inputStream.close();
  56. }
  57. if(inputChannel !=null){
  58. inputChannel.close();
  59. }
  60. if(outputChannel !=null){
  61. outputChannel.close();
  62. }
  63. if(outputStream !=null){
  64. outputStream.close();
  65. }
  66. }
  67. long end=System.currentTimeMillis();
  68. System.out.println("非缓冲区复制文件耗时:"+(end-start));
  69. return result;
  70. }
  71. /** * 2.利用通道进行本地文件的复制功能(直接缓冲区,利用内存映射文件) * @param copyFrom * @param copyTo * @return boolean */
  72. public boolean copyFileByChannel2Direct(String copyFrom,String copyTo) throws IOException {
  73. long start=System.currentTimeMillis();
  74. //1.获取输入输出通道
  75. FileChannel inputChannel= FileChannel.open(Paths.get(copyFrom), StandardOpenOption.READ);
  76. FileChannel outputChannel=FileChannel.open(Paths.get(copyTo),StandardOpenOption.WRITE,StandardOpenOption.READ,StandardOpenOption.CREATE);
  77. //2.获取内存映射文件
  78. MappedByteBuffer inMappedBuf=inputChannel.map(FileChannel.MapMode.READ_ONLY,0,inputChannel.size());
  79. MappedByteBuffer outMappedBuf=outputChannel.map(FileChannel.MapMode.READ_WRITE,0,inputChannel.size());
  80. //3.直接对缓冲区进行读写操作
  81. byte[] dst=new byte[inMappedBuf.limit()];
  82. inMappedBuf.get(dst);
  83. outMappedBuf.put(dst);
  84. //4.关闭输入输出通道
  85. inputChannel.close();
  86. outputChannel.close();
  87. long end =System.currentTimeMillis();
  88. System.out.println("直接缓冲区复制的耗时:"+(end-start));
  89. return true;
  90. }
  91. /** * 3.通道之间的数据传输(直接缓冲区) * @param copyFrom * @param copyTo * @return boolean */
  92. public boolean copyFileByChannel2Transfer(String copyFrom,String copyTo) throws IOException {
  93. FileChannel inChannel=FileChannel.open(Paths.get(copyFrom),StandardOpenOption.READ);
  94. FileChannel outChannel=FileChannel.open(Paths.get(copyTo),StandardOpenOption.WRITE,StandardOpenOption.READ,StandardOpenOption.CREATE);
  95. //1.将通道中的字节数据传输到指定通道,transferTo()
  96. inChannel.transferTo(0,inChannel.size(),outChannel);
  97. //2.从指定通道中获取自己数据到通道中,transferFrom()
  98. //outChannel.transferFrom(inChannel,0,inChannel.size());
  99. return true;
  100. }
  101. /** * 4.通道的分散和聚合 *分散读取:将通道的数据读取到多个缓冲区Bufer中 * 聚集写入:将多个缓冲区的数据聚集写到通道Channel中 * @param writeFlie * @param readFlie */
  102. public void channelWriteAndRead(String writeFlie,String readFlie) throws IOException {
  103. //1.读取指定文件
  104. RandomAccessFile randomAccessFile=new RandomAccessFile(readFlie,"rw");
  105. //2.获取本地文件通道
  106. FileChannel fileChannel=randomAccessFile.getChannel();
  107. //3.分配指定大小的缓冲区
  108. ByteBuffer buf1=ByteBuffer.allocate(1024);//设置多大就缓存多大
  109. ByteBuffer buf2=ByteBuffer.allocate(1024);
  110. //4.分散读取
  111. ByteBuffer[] bufs={ buf1,buf2};
  112. fileChannel.read(bufs);
  113. for(ByteBuffer byteBuffer:bufs){
  114. byteBuffer.flip();
  115. System.out.println("每个缓冲区的数据如下:");
  116. System.out.println(new String(byteBuffer.array(),0,byteBuffer.limit()));
  117. }
  118. //5.聚集写入(指定文件)
  119. RandomAccessFile randomAccessFile1=new RandomAccessFile(writeFlie,"rw");//指定写到那个文件下
  120. FileChannel fileChannel1=randomAccessFile1.getChannel();
  121. fileChannel1.write(bufs);
  122. }
  123. }
  124. //创建线程1测试,非缓冲区文件复制
  125. class copyFileThread1 implements Runnable{
  126. ChannelDome channelDome=new ChannelDome();
  127. String copyFrom="G:\\copyFromFile\\copyForm.log";
  128. String copyTo="H:\\copyToFile\\NoDirect\\copyTo1.log";
  129. @Override
  130. public void run() {
  131. try {
  132. System.out.println(Thread.currentThread() +"当前线程正在执行利用非缓冲区本地文件复制功能");
  133. channelDome.copyFileByChannel(copyFrom,copyTo);
  134. } catch (IOException e) {
  135. e.printStackTrace();
  136. }
  137. }
  138. }
  139. //创建线程2测试,
  140. class copyFileThread2 implements Runnable{
  141. ChannelDome channelDome =new ChannelDome();
  142. String copyFrom="G:\\copyFromFile\\copyForm.log";
  143. String copyTo="H:\\copyToFile\\Direct\\copyTo2.log";
  144. @Override
  145. public void run() {
  146. try {
  147. System.out.println(Thread.currentThread() +"当前线程正在执行利用缓冲区本地文件复制功能");
  148. channelDome.copyFileByChannel2Direct(copyFrom,copyTo);
  149. } catch (IOException e) {
  150. e.printStackTrace();
  151. }
  152. }
  153. }
  154. //通道的分散读取和聚集写入线程测试
  155. class channelWriteAndRead implements Runnable{
  156. ChannelDome channelDome=new ChannelDome();
  157. String writeFile="G:\\copyFromFile\\copyForm.log";
  158. String readFile="H:\\copyToFile\\Read\\read.log";
  159. @Override
  160. public void run() {
  161. try {
  162. System.out.println(Thread.currentThread() +"当前线程正在执行通道的分散读取和聚集写入线程功能");
  163. channelDome.channelWriteAndRead(readFile,writeFile);
  164. } catch (IOException e) {
  165. e.printStackTrace();
  166. }
  167. }
  168. }
  169. //通道之间的传输线程测试
  170. class channelTransfer implements Runnable{
  171. ChannelDome channelDome=new ChannelDome();
  172. String copyForm="G:\\copyFromFile\\copyForm.log";
  173. String copyTo="H:\\copyToFile\\transfer\\transfer.log";
  174. @Override
  175. public void run() {
  176. try {
  177. System.out.println(Thread.currentThread() +"当前线程正在执行通道之间的传输线程功能");
  178. channelDome.copyFileByChannel2Transfer(copyForm,copyTo);
  179. } catch (IOException e) {
  180. e.printStackTrace();
  181. }
  182. }
  183. }

控制台输出结果

在这里插入图片描述

发表评论

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

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

相关阅读

    相关 Java NIO Channel

    定义 用于源节点和目标节点之间的连接。nio中负责缓冲区中数据传输,Channel本地并不存储数据,而是配合缓冲区进行数据传输。你可以把它理解成io中的流。 结