• NIO系列——通道(Channel)


      1 import java.io.FileInputStream;
      2 import java.io.FileOutputStream;
      3 import java.io.IOException;
      4 import java.io.RandomAccessFile;
      5 import java.nio.ByteBuffer;
      6 import java.nio.CharBuffer;
      7 import java.nio.MappedByteBuffer;
      8 import java.nio.channels.FileChannel;
      9 import java.nio.channels.FileChannel.MapMode;
     10 import java.nio.charset.CharacterCodingException;
     11 import java.nio.charset.Charset;
     12 import java.nio.charset.CharsetDecoder;
     13 import java.nio.charset.CharsetEncoder;
     14 import java.nio.file.Paths;
     15 import java.nio.file.StandardOpenOption;
     16 import java.util.Map;
     17 import java.util.Map.Entry;
     18 import java.util.Set;
     19 
     20 import org.junit.Test;
     21 
     22 /*
     23  * 一、通道(Channel):用于源节点与目标节点的连接。在 Java NIO 中负责缓冲区中数据的传输。Channel 本身不存储数据,因此需要配合缓冲区进行传输。
     24  * 
     25  * 二、通道的主要实现类
     26  *     java.nio.channels.Channel 接口:
     27  *         |--FileChannel
     28  *         |--SocketChannel
     29  *         |--ServerSocketChannel
     30  *         |--DatagramChannel
     31  * 
     32  * 三、获取通道
     33  * 1. Java 针对支持通道的类提供了 getChannel() 方法
     34  *         本地 IO:
     35  *         FileInputStream/FileOutputStream
     36  *         RandomAccessFile
     37  * 
     38  *         网络IO:
     39  *         Socket
     40  *         ServerSocket
     41  *         DatagramSocket
     42  *         
     43  * 2. 在 JDK 1.7 中的 NIO.2 针对各个通道提供了静态方法 open()
     44  * 3. 在 JDK 1.7 中的 NIO.2 的 Files 工具类的 newByteChannel()
     45  * 
     46  * 四、通道之间的数据传输
     47  * transferFrom()
     48  * transferTo()
     49  * 
     50  * 五、分散(Scatter)与聚集(Gather)
     51  * 分散读取(Scattering Reads):将通道中的数据分散到多个缓冲区中
     52  * 聚集写入(Gathering Writes):将多个缓冲区中的数据聚集到通道中
     53  * 
     54  * 六、字符集:Charset
     55  * 编码:字符串 -> 字节数组
     56  * 解码:字节数组  -> 字符串
     57  * 
     58  */
     59 public class TestChannel {
     60     
     61     //字符集
     62     @Test
     63     public void test6() throws IOException{
     64         Charset cs1 = Charset.forName("GBK");
     65         
     66         //获取编码器
     67         CharsetEncoder ce = cs1.newEncoder();
     68         
     69         //获取解码器
     70         CharsetDecoder cd = cs1.newDecoder();
     71         
     72         CharBuffer cBuf = CharBuffer.allocate(1024);
     73         cBuf.put("好好学习天天向上!");
     74         cBuf.flip();
     75         
     76         //编码
     77         ByteBuffer bBuf = ce.encode(cBuf);
     78         
     79         for (int i = 0; i < 12; i++) {
     80             System.out.println(bBuf.get());
     81         }
     82         
     83         //解码
     84         bBuf.flip();
     85         CharBuffer cBuf2 = cd.decode(bBuf);
     86         System.out.println(cBuf2.toString());
     87         
     88         System.out.println("------------------------------------------------------");
     89         
     90         Charset cs2 = Charset.forName("GBK");
     91         bBuf.flip();
     92         CharBuffer cBuf3 = cs2.decode(bBuf);
     93         System.out.println(cBuf3.toString());
     94     }
     95     
     96     @Test
     97     public void test5(){
     98         Map<String, Charset> map = Charset.availableCharsets();
     99         
    100         Set<Entry<String, Charset>> set = map.entrySet();
    101         
    102         for (Entry<String, Charset> entry : set) {
    103             System.out.println(entry.getKey() + "=" + entry.getValue());
    104         }
    105     }
    106     
    107     //分散和聚集
    108     @Test
    109     public void test4() throws IOException{
    110         RandomAccessFile raf1 = new RandomAccessFile("1.txt", "rw");
    111         
    112         //1. 获取通道
    113         FileChannel channel1 = raf1.getChannel();
    114         
    115         //2. 分配指定大小的缓冲区
    116         ByteBuffer buf1 = ByteBuffer.allocate(100);
    117         ByteBuffer buf2 = ByteBuffer.allocate(1024);
    118         
    119         //3. 分散读取
    120         ByteBuffer[] bufs = {buf1, buf2};
    121         channel1.read(bufs);
    122         
    123         for (ByteBuffer byteBuffer : bufs) {
    124             byteBuffer.flip();
    125         }
    126         
    127         System.out.println(new String(bufs[0].array(), 0, bufs[0].limit()));
    128         System.out.println("-----------------");
    129         System.out.println(new String(bufs[1].array(), 0, bufs[1].limit()));
    130         
    131         //4. 聚集写入
    132         RandomAccessFile raf2 = new RandomAccessFile("2.txt", "rw");
    133         FileChannel channel2 = raf2.getChannel();
    134         
    135         channel2.write(bufs);
    136     }
    137     
    138     //通道之间的数据传输(直接缓冲区)
    139     @Test
    140     public void test3() throws IOException{
    141         FileChannel inChannel = FileChannel.open(Paths.get("d:/1.mkv"), StandardOpenOption.READ);
    142         FileChannel outChannel = FileChannel.open(Paths.get("d:/2.mkv"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);
    143         
    144 //        inChannel.transferTo(0, inChannel.size(), outChannel);
    145         outChannel.transferFrom(inChannel, 0, inChannel.size());
    146         
    147         inChannel.close();
    148         outChannel.close();
    149     }
    150     
    151     //使用直接缓冲区完成文件的复制(内存映射文件)
    152     @Test
    153     public void test2() throws IOException{//2127-1902-1777
    154         long start = System.currentTimeMillis();
    155         
    156         FileChannel inChannel = FileChannel.open(Paths.get("d:/1.mkv"), StandardOpenOption.READ);
    157         FileChannel outChannel = FileChannel.open(Paths.get("d:/2.mkv"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);
    158         
    159         //内存映射文件
    160         MappedByteBuffer inMappedBuf = inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());
    161         MappedByteBuffer outMappedBuf = outChannel.map(MapMode.READ_WRITE, 0, inChannel.size());
    162         
    163         //直接对缓冲区进行数据的读写操作
    164         byte[] dst = new byte[inMappedBuf.limit()];
    165         inMappedBuf.get(dst);
    166         outMappedBuf.put(dst);
    167         
    168         inChannel.close();
    169         outChannel.close();
    170         
    171         long end = System.currentTimeMillis();
    172         System.out.println("耗费时间为:" + (end - start));
    173     }
    174     
    175     //利用通道完成文件的复制(非直接缓冲区)
    176     @Test
    177     public void test1(){//10874-10953
    178         long start = System.currentTimeMillis();
    179         
    180         FileInputStream fis = null;
    181         FileOutputStream fos = null;
    182         //①获取通道
    183         FileChannel inChannel = null;
    184         FileChannel outChannel = null;
    185         try {
    186             fis = new FileInputStream("d:/1.mkv");
    187             fos = new FileOutputStream("d:/2.mkv");
    188             
    189             inChannel = fis.getChannel();
    190             outChannel = fos.getChannel();
    191             
    192             //②分配指定大小的缓冲区
    193             ByteBuffer buf = ByteBuffer.allocate(1024);
    194             
    195             //③将通道中的数据存入缓冲区中
    196             while(inChannel.read(buf) != -1){
    197                 buf.flip(); //切换读取数据的模式
    198                 //④将缓冲区中的数据写入通道中
    199                 outChannel.write(buf);
    200                 buf.clear(); //清空缓冲区
    201             }
    202         } catch (IOException e) {
    203             e.printStackTrace();
    204         } finally {
    205             if(outChannel != null){
    206                 try {
    207                     outChannel.close();
    208                 } catch (IOException e) {
    209                     e.printStackTrace();
    210                 }
    211             }
    212             
    213             if(inChannel != null){
    214                 try {
    215                     inChannel.close();
    216                 } catch (IOException e) {
    217                     e.printStackTrace();
    218                 }
    219             }
    220             
    221             if(fos != null){
    222                 try {
    223                     fos.close();
    224                 } catch (IOException e) {
    225                     e.printStackTrace();
    226                 }
    227             }
    228             
    229             if(fis != null){
    230                 try {
    231                     fis.close();
    232                 } catch (IOException e) {
    233                     e.printStackTrace();
    234                 }
    235             }
    236         }
    237         
    238         long end = System.currentTimeMillis();
    239         System.out.println("耗费时间为:" + (end - start));
    240         
    241     }
    242 
    243 }
    纸上学来终觉浅,觉知此事需躬行
  • 相关阅读:
    jQuery上传插件Uploadify使用详解
    SQL之case when then用法
    myeclipse 上安装 Maven
    ps 简介
    Linux 查看进程和删除进程
    EL表达<%@page isELIgnored="false"%>问题
    刷新本地的DNS缓存
    IDEA中 @override报错的处理步骤
    Caused by: org.springframework.core.NestedIOException: ASM ClassReader failed to parse class file
    jsp中${param.user}不解析,原样输出。
  • 原文地址:https://www.cnblogs.com/dreamHighMjc/p/8185228.html
Copyright © 2020-2023  润新知