zoukankan      html  css  js  c++  java
  • NIO-2通道(Channel)

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.RandomAccessFile;
    import java.nio.ByteBuffer;
    import java.nio.CharBuffer;
    import java.nio.MappedByteBuffer;
    import java.nio.channels.FileChannel;
    import java.nio.channels.FileChannel.MapMode;
    import java.nio.charset.CharacterCodingException;
    import java.nio.charset.Charset;
    import java.nio.charset.CharsetDecoder;
    import java.nio.charset.CharsetEncoder;
    import java.nio.file.Paths;
    import java.nio.file.StandardOpenOption;
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.Set;
    
    import org.junit.Test;
    
    /*
     * 一、通道(Channel):用于源节点与目标节点的连接。在 Java NIO 中负责缓冲区中数据的传输。Channel 本身不存储数据,因此需要配合缓冲区进行传输。
     * 
     * 二、通道的主要实现类
     *     java.nio.channels.Channel 接口:
     *         |--FileChannel
     *         |--SocketChannel
     *         |--ServerSocketChannel
     *         |--DatagramChannel
     * 
     * 三、获取通道
     * 1. Java 针对支持通道的类提供了 getChannel() 方法
     *         本地 IO:
     *         FileInputStream/FileOutputStream
     *         RandomAccessFile
     * 
     *         网络IO:
     *         Socket
     *         ServerSocket
     *         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
     * 编码:字符串 -> 字节数组
     * 解码:字节数组  -> 字符串
     * 
     */
    public class TestChannel {
        
        //字符集
        @Test
        public void test6() throws IOException{
            Charset cs1 = Charset.forName("GBK");
            
            //获取编码器
            CharsetEncoder ce = cs1.newEncoder();
            
            //获取解码器
            CharsetDecoder cd = cs1.newDecoder();
            
            CharBuffer cBuf = CharBuffer.allocate(1024);
            cBuf.put("尚硅谷威武!");
            cBuf.flip();
            
            //编码
            ByteBuffer bBuf = ce.encode(cBuf);
            
            for (int i = 0; i < 12; i++) {
                System.out.println(bBuf.get());
            }
            
            //解码
            bBuf.flip();
            CharBuffer cBuf2 = cd.decode(bBuf);
            System.out.println(cBuf2.toString());
            
            System.out.println("------------------------------------------------------");
            
            Charset cs2 = Charset.forName("GBK");
            bBuf.flip();
            CharBuffer cBuf3 = cs2.decode(bBuf);
            System.out.println(cBuf3.toString());
        }
        
        @Test
        public void test5(){
            Map<String, Charset> map = Charset.availableCharsets();
            
            Set<Entry<String, Charset>> set = map.entrySet();
            
            for (Entry<String, Charset> entry : set) {
                System.out.println(entry.getKey() + "=" + entry.getValue());
            }
        }
        
        //分散和聚集
        @Test
        public void test4() throws IOException{
            RandomAccessFile raf1 = new RandomAccessFile("1.txt", "rw");
            
            //1. 获取通道
            FileChannel channel1 = raf1.getChannel();
            
            //2. 分配指定大小的缓冲区
            ByteBuffer buf1 = ByteBuffer.allocate(100);
            ByteBuffer buf2 = ByteBuffer.allocate(1024);
            
            //3. 分散读取
            ByteBuffer[] bufs = {buf1, buf2};
            channel1.read(bufs);
            
            for (ByteBuffer byteBuffer : bufs) {
                byteBuffer.flip();
            }
            
            System.out.println(new String(bufs[0].array(), 0, bufs[0].limit()));
            System.out.println("-----------------");
            System.out.println(new String(bufs[1].array(), 0, bufs[1].limit()));
            
            //4. 聚集写入
            RandomAccessFile raf2 = new RandomAccessFile("2.txt", "rw");
            FileChannel channel2 = raf2.getChannel();
            
            channel2.write(bufs);
        }
        
        //通道之间的数据传输(直接缓冲区)
        @Test
        public void test3() throws IOException{
            FileChannel inChannel = FileChannel.open(Paths.get("d:/1.mkv"), StandardOpenOption.READ);
            FileChannel outChannel = FileChannel.open(Paths.get("d:/2.mkv"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);
            
    //        inChannel.transferTo(0, inChannel.size(), outChannel);
            outChannel.transferFrom(inChannel, 0, inChannel.size());
            
            inChannel.close();
            outChannel.close();
        }
        
        //使用直接缓冲区完成文件的复制(内存映射文件)
        @Test
        public void test2() throws IOException{//2127-1902-1777
            long start = System.currentTimeMillis();
            
            FileChannel inChannel = FileChannel.open(Paths.get("d:/1.mkv"), StandardOpenOption.READ);
            FileChannel outChannel = FileChannel.open(Paths.get("d:/2.mkv"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);
            
            //内存映射文件
            MappedByteBuffer inMappedBuf = inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());
            MappedByteBuffer outMappedBuf = outChannel.map(MapMode.READ_WRITE, 0, inChannel.size());
            
            //直接对缓冲区进行数据的读写操作
            byte[] dst = new byte[inMappedBuf.limit()];
            inMappedBuf.get(dst);
            outMappedBuf.put(dst);
            
            inChannel.close();
            outChannel.close();
            
            long end = System.currentTimeMillis();
            System.out.println("耗费时间为:" + (end - start));
        }
        
        //利用通道完成文件的复制(非直接缓冲区)
        @Test
        public void test1(){//10874-10953
            long start = System.currentTimeMillis();
            
            FileInputStream fis = null;
            FileOutputStream fos = null;
            //①获取通道
            FileChannel inChannel = null;
            FileChannel outChannel = null;
            try {
                fis = new FileInputStream("d:/1.mkv");
                fos = new FileOutputStream("d:/2.mkv");
                
                inChannel = fis.getChannel();
                outChannel = fos.getChannel();
                
                //②分配指定大小的缓冲区
                ByteBuffer buf = ByteBuffer.allocate(1024);
                
                //③将通道中的数据存入缓冲区中
                while(inChannel.read(buf) != -1){
                    buf.flip(); //切换读取数据的模式
                    //④将缓冲区中的数据写入通道中
                    outChannel.write(buf);
                    buf.clear(); //清空缓冲区
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if(outChannel != null){
                    try {
                        outChannel.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                
                if(inChannel != null){
                    try {
                        inChannel.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                
                if(fos != null){
                    try {
                        fos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                
                if(fis != null){
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            
            long end = System.currentTimeMillis();
            System.out.println("耗费时间为:" + (end - start));
            
        }
    
    }
  • 相关阅读:
    公用表表达式(CTE)的递归调用
    c# 如何让tooltip显示文字换行
    实战 SQL Server 2008 数据库误删除数据的恢复
    SQL SERVER数据库中 是否可以对视图进行修改删除
    asp.net中实现文件批量上传
    sql server 2008学习2 文件和文件组
    sql server 2008学习3 表组织和索引组织
    sql server 2008学习4 设计索引的建议
    sql server 2008学习10 存储过程
    .net 调用 sql server 自定义函数,并输出返回值
  • 原文地址:https://www.cnblogs.com/surge/p/10476082.html
Copyright © 2011-2022 走看看