NIO实践

NIO实践

Read

    /**

     * NIO读取流

     * 1. 创建channel

     * 2. 创建buffer

     * 3. 从channel读取到buffer

     *

     * @param inputStream

     */

    public void NIORead(FileInputStream inputStream) {

        FileChannel fileChannel = inputStream.getChannel();  //获取一个文件管道

        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);  //获取一个ByteBuffer

        int len = 0;

        try {

            StringBuilder sb = new StringBuilder();

            while ((len = fileChannel.read(byteBuffer)) > -1) {   //管道的read方法:从通道读取到缓冲区,读了多少就返回最后的位置,如果读到流的末尾,返回-1

                byteBuffer.flip();  //开启缓冲区读取模式,重置postion位置为0,limit为position位置

                sb.append(new String(byteBuffer.array(), 0, len));

            }

            System.out.println("sb.tostring =" + sb.toString());

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

 

Write:

    public void writeNIO(FileOutputStream fileOutputStream) {

        String writeMsg = "测试写入文件NIO";

        FileChannel fileChannel = fileOutputStream.getChannel(); //打开管道,管道是双向的,可以读,可以写

        byte[] bytes = writeMsg.getBytes();

        try {

            fileChannel.write(ByteBuffer.wrap(bytes, 0, bytes.length)); //写入到buffer,如果下次再写,记得clear buffer

        } catch (IOException e) {

            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.

        }

 

    }

Copy文件:

    /**

     * 利用nio的读写完成一次文件的拷贝。

     */

    public void copyFile() {

        File fileFrom = new File("D:\\appstore-gateway-debug.log");

        File fileTo = new File("D:\\test.txt");

 

        try {

            FileInputStream fileInputStream = new FileInputStream(fileFrom);

            FileChannel channelFrom = fileInputStream.getChannel();     //创建输入管道

 

            FileOutputStream fileOutputStream = new FileOutputStream(fileTo);

            FileChannel chanelTo = fileOutputStream.getChannel();   //创建输出管道

 

            int len = 0;

            ByteBuffer byteBuffer = ByteBuffer.allocate(1024); //创建缓冲区

            StringBuilder sb = new StringBuilder();

            while ((len = channelFrom.read(byteBuffer)) > -1) {

                byteBuffer.flip();//切换到写模式,position设为0,否则写不了

                sb.append(new String(byteBuffer.array(), 0, len));

                chanelTo.write(byteBuffer); //把缓冲区的数据写入到写管道

                byteBuffer.clear();   //写完后clear一下,重置position和limit,方便下次的读取

            }

            System.out.println("拷贝结束" + sb.toString());

 

        } catch (FileNotFoundException e) {

            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.

        } catch (IOException e) {

            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.

      

按行读取:

这里模拟了一个生产者消费者模型,通过nio读取大文件,每行的数据加入阻塞队列,之后开启消费者线程消费这些数据。

  public static void bigFileRead(String inputPath) {

        //输出

        File fileInput = new File(inputPath);

        FileChannel fcout = null;

        try {

            FileChannel fcin = new RandomAccessFile(fileInput, "r").getChannel();

            ByteBuffer rBuffer = ByteBuffer.allocate(bufSize);

            readFileByLine(fcin, rBuffer);

        } catch (FileNotFoundException e) {

            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.

        }

 

    }

 

 

    /**

     * 按行读写文件

     *

     * @param fcin    输入channel

     * @param rBuffer 读buffer

     * @throws FileNotFoundException

     */

    public static void readFileByLine(FileChannel fcin, ByteBuffer rBuffer) throws FileNotFoundException {

 

        //3.遍历总表";与目标表比较。用正则匹配";

        try {

            byte[] bs = new byte[bufSize];

            StringBuffer strBuf = new StringBuffer("");

            int rSize;

            while (fcin.read(rBuffer) != -1) {

                rSize = rBuffer.position(); //得到当前读取的单位数据位置。

                rBuffer.rewind(); //将position置为0,用于重复读

                rBuffer.get(bs, 0, rSize);  //获取 bufSize个字节的数据到buffer

                rBuffer.clear();   //清空buffer,准备再次被写入,position变为0,limit变为capacity

 

                String tempString = new String(bs); //得到读取的字符串

                int fromIndex = 0;

                int endIndex = 0;

                while ((endIndex = tempString.indexOf(ENTERSTR, fromIndex)) != -1) {

                    String line = tempString.substring(fromIndex, endIndex);  //按行取字符串

                    line = strBuf.append(line).toString();

                    // 拿到字符串后开始处理匹配逻辑

//                    System.out.println("line=" + line);

                    try {

                        blockingQueue.put(line);//加入生产者线程

                    } catch (InterruptedException e) {

                        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.

                    }

                    strBuf.delete(0, strBuf.length());

                    fromIndex = endIndex + 1;

                }

                //每次只取1024个字节,而excel1024个字节可能对应的行数是不定的,所以肯定有剩余字符,这里是对它们的处理

                if (rSize > tempString.length()) {

                    strBuf.append(tempString.substring(fromIndex, tempString.length()));

                } else {

                    if (fromIndex < rSize)

                        strBuf.append(tempString.substring(fromIndex, rSize));

                }

            }

 

            fcin.close();

        } catch (IOException e) {

            e.printStackTrace();

        }

 

    }

}

消费者线程核心代码:

   while (flag) {

                        String s = (String) SimpleReadWrite.blockingQueue.take();

                        if (s == SimpleReadWrite.dummy) { //处理哑对象,方便线程退出

                            SimpleReadWrite.blockingQueue.put(SimpleReadWrite.dummy);

                            flag = false;

                        } else {

                            dosthTrim(s); //当trimFlag为true时才执行trim方法

                        }

                    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值