zoukankan      html  css  js  c++  java
  • nio初认识之channel

    一.bio与nio区别

    IONIO
    面向流(Stream Orientend) 面向缓冲区(Buffer Orientend)
    阻塞IO(Blocking IO ) 非阻塞IO(Non Blocking IO)
      选择器(Selector)

    二.通道(Channel )
      通道表示打开到 IO 设备(例如:文件、套接字)的连接。若需要使用 NIO 系统,需要获取用于连接 IO 设备的通道以及用于容纳数据的缓冲区。然后操作缓冲区,对数据进行处理。
      Channel相比IO中的Stream更加高效,可以异步双向传输,但是必须和buffer一起使用。

    三.Channel主要实现类
    FileChannel,读写文件中的数据。
    SocketChannel,通过TCP读写网络中的数据。
    ServerSockectChannel,监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。
    DatagramChannel,通过UDP读写网络中的数据。

    四.Channel主要获取方式
      1、java针对支持通道的类提供了getChannel()方法

    本地io:
       FileInputStreanm/FileOutputStream
      RandomAccessFile
    网络io:
      Socket
      ServerSocket
      DatagramSocket

    五.代码实例

    package com.tcc.test.nio.channel;
    
    import org.junit.Test;
    
    import java.io.*;
    import java.nio.ByteBuffer;
    import java.nio.MappedByteBuffer;
    import java.nio.channels.FileChannel;
    
    /**
     * Copyright (C) @2021
     *
     * @author: tcc
     * @version: 1.0
     * @date: 2021/11/28
     * @time: 17:37
     * @description:
     */
    public class channeltest {
    
        //文件复制
        @Test
        public void test() throws Exception {
            FileInputStream fis = new FileInputStream("D:\\1.jpg");
            FileOutputStream fos = new FileOutputStream("D:\\2.jpg");
            //获取通道
            FileChannel inChannel = fis.getChannel();
            FileChannel outChannel = fos.getChannel();
            //分配指定大小缓存区
            ByteBuffer buff = ByteBuffer.allocate(1024);// position 0 ,limit 1024
            //将通道的数据存入缓存区
            while (inChannel.read(buff) != -1) {// position 1024 ,limit 1024 ,相当于put
                //切换读模式
                buff.flip();//position 0 ,limit 1024
                //将缓存去的数据写入通道
                outChannel.write(buff);//position 1024 ,limit 1024,相当于get
                //清空缓冲区
                buff.clear();//position 0 ,limit 1024
            }
            outChannel.close();
            inChannel.close();
            fis.close();
            fos.close();
        }
    
        //一个文件读其中一部分
        @Test
        public void test2() throws IOException {
            String fff = "D:\\test.txt";
            final int BUFFER_SIZE = 0x300000;// 缓冲区大小为3M
    
            File f = new File(fff);
    
            /**
             *
             * map(FileChannel.MapMode mode,long position, long size)
             *
             * mode - 根据是按只读、读取/写入或专用(写入时拷贝)来映射文件,分别为 FileChannel.MapMode 类中所定义的
             * READ_ONLY、READ_WRITE 或 PRIVATE 之一
             *
             * position - 文件中的位置,映射区域从此位置开始;必须为非负数
             *
             * size - 要映射的区域大小;必须为非负数且不大于 Integer.MAX_VALUE
             *
             * 所以若想读取文件后半部分内容,如例子所写;若想读取文本后1/8内容,需要这样写map(FileChannel.MapMode.READ_ONLY,
             * f.length()*7/8,f.length()/8)
             *
             * 想读取文件所有内容,需要这样写map(FileChannel.MapMode.READ_ONLY, 0,f.length())
             *
             */
    
            MappedByteBuffer inputBuffer = new RandomAccessFile(f, "r")
                    .getChannel().map(FileChannel.MapMode.READ_ONLY,
                            f.length() / 2, f.length() / 2);
    
            byte[] dst = new byte[BUFFER_SIZE];// 每次读出3M的内容
    
            long start = System.currentTimeMillis();
    
            for (int offset = 0; offset < inputBuffer.capacity(); offset += BUFFER_SIZE) {
    
                if (inputBuffer.capacity() - offset >= BUFFER_SIZE) {
    
                    for (int i = 0; i < BUFFER_SIZE; i++)
    
                        dst[i] = inputBuffer.get(offset + i);
    
                } else {
    
                    for (int i = 0; i < inputBuffer.capacity() - offset; i++)
    
                        dst[i] = inputBuffer.get(offset + i);
    
                }
    
                int length = (inputBuffer.capacity() % BUFFER_SIZE == 0) ? BUFFER_SIZE
                        : inputBuffer.capacity() % BUFFER_SIZE;
    
                System.out.println(new String(dst, 0, length));// new
                // String(dst,0,length)这样可以取出缓存保存的字符串,可以对其进行操作
    
            }
    
            long end = System.currentTimeMillis();
    
            System.out.println("读取文件文件一半内容花费:" + (end - start) + "毫秒");
        }
    
        //全部一次性读
        @Test
        public void test3() throws IOException {
            String fff = "D:\\test.txt";
            int bufSize = 1024;
            byte[] bs = new byte[bufSize];
            ByteBuffer byteBuf = ByteBuffer.allocate(1024);
            FileChannel channel = new RandomAccessFile(fff, "r").getChannel();
            while (channel.read(byteBuf) != -1) {
                int size = byteBuf.position();
                byteBuf.rewind();
                byteBuf.get(bs); // 把文件当字符串处理,直接打印做为一个例子。
                System.out.print(new String(bs, 0, size));
                byteBuf.clear();
            }
    
        }
    
        //一行行读
        @Test
        public void test4() throws IOException {
            String fff = "D:\\test.txt";
            BufferedReader br = new BufferedReader(new FileReader(fff));
            String line = null;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        }
    
    
        //每次读取几行
        @Test
        public void test5() throws IOException {
            String path = "D:\\test.txt";
            RandomAccessFile br = new RandomAccessFile(path, "rw");//这里rw看你了。要是之都就只写r
            String str = null, app = null;
            int i = 0;
            while ((str = br.readLine()) != null) {
                i++;
                app = app + str;
                System.out.println("app=="+app);
                if (i >= 2) {//假设读取100行
                    i = 0;
    // 这里你先对这100行操作,然后继续读
                    System.out.println("app22"+app);
                    app = null;
                }
            }
            br.close();
        }
    
    
        //BufferedReader类读写超大文件,一行行读
        @Test
        public void test6() throws IOException {
            String filepath = "D:\\test.txt";
            File file = new File(filepath);
            BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file));
            BufferedReader reader = new BufferedReader(new InputStreamReader(fis,"utf-8"),5*1024*1024);// 用5M的缓冲读取文本文件
    
            String line = "";
            while((line = reader.readLine()) != null){
                System.out.println("line==="+line);
            //TODO: write your business
            }
        }
    
    }
  • 相关阅读:
    洛朗级数
    泰勒级数
    中心极限定理
    置信区间公式
    简单随机样本的性质
    极大似然估计
    矩估计法
    摆摊70
    天天去哪吃
    天天和树
  • 原文地址:https://www.cnblogs.com/tongcc/p/15616159.html
Copyright © 2011-2022 走看看