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
            }
        }
    
    }
  • 相关阅读:
    Java学习二十九天
    Java学习二十八天
    47. Permutations II 全排列可重复版本
    46. Permutations 全排列,无重复
    subset ii 子集 有重复元素
    339. Nested List Weight Sum 339.嵌套列表权重总和
    251. Flatten 2D Vector 平铺二维矩阵
    217. Contains Duplicate数组重复元素
    209. Minimum Size Subarray Sum 结果大于等于目标的最小长度数组
    438. Find All Anagrams in a String 查找字符串中的所有Anagrams
  • 原文地址:https://www.cnblogs.com/tongcc/p/15616159.html
Copyright © 2011-2022 走看看