Java使用BIO和NIO进行文件操作对比代码示例

什么是Java NIO?

同步非阻塞io模式,拿烧开水来说,NIO的做法是叫一个线程不断的轮询每个水壶的状态,看看是否有水壶的状态发生了改变,从而进行下一步的操作。
Java NIO有三大组成部分:Buffer,Channel,Selector,通过事件驱动模式实现了什么时候有数据可读的问题。

什么是Java BIO?

同步阻塞IO模式,数据的读取写入必须阻塞在一个线程内等待其完成。这里使用那个经典的烧开水例子,这里假设一个烧开水的场景,有一排水壶在烧开水,BIO的工作模式就是, 叫一个线程停留在一个水壶那,直到这个水壶烧开,才去处理下一个水壶。但是实际上线程在等待水壶烧开的时间段什么都没有做。不知道io操作中什么时候有数据可读,所以一直是阻塞的模式。

1、读文件

package com.zhi.test;

import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.file.Files;
import java.nio.file.Paths;

/**
 * 文件读取,缓冲区大小(BF_SIZE)对NIO的性能影响特别大,对BIO无影响<br>
 * 10M的文件,BIO耗时87毫秒,NIO耗时68毫秒,Files.read耗时62毫秒
 *
 * @author 张远志
 * @since 2020年5月9日19:20:49
 *
 */
public class FileRead {
  /**
   * 缓冲区大小
   */
  private static final int BF_SIZE = 1024;

  /**
   * 使用BIO读取文件
   *
   * @param fileName 待读文件名
   * @return
   * @throws IOException
   */
  public static String bioRead(String fileName) throws IOException {
    long startTime = System.currentTimeMillis();
    try {
      FileReader reader = new FileReader(fileName);

      StringBuffer buf = new StringBuffer();
      char[] cbuf = new char[BF_SIZE];
      while (reader.read(cbuf) != -1) {
        buf.append(cbuf);
      }
      reader.close();
      return buf.toString();
    } finally {
      System.out.println("使用BIO读取文件耗时:" + (System.currentTimeMillis() - startTime) + "毫秒");
    }
  }

  /**
   * 使用NIO读取文件
   *
   * @param fileName 待读文件名
   * @return
   * @throws IOException
   */
  public static String nioRead1(String fileName) throws IOException {
    long startTime = System.currentTimeMillis();
    try {
      FileInputStream input = new FileInputStream(fileName);
      FileChannel channel = input.getChannel();

      CharsetDecoder decoder = Charset.defaultCharset().newDecoder();
      StringBuffer buf = new StringBuffer();
      CharBuffer cBuf = CharBuffer.allocate(BF_SIZE);
      ByteBuffer bBuf = ByteBuffer.allocate(BF_SIZE);
      while (channel.read(bBuf) != -1) {
        bBuf.flip();
        decoder.decode(bBuf, cBuf, false); // 解码,byte转char,最后一个参数非常关键
        bBuf.clear();
        buf.append(cBuf.array(), 0, cBuf.position());
        cBuf.compact(); // 压缩
      }
      input.close();
      return buf.toString();
    } finally {
      System.out.println("使用NIO读取文件耗时:" + (System.currentTimeMillis() - startTime) + "毫秒");
    }
  }

  /**
   * 使用Files.read读取文件
   *
   * @param fileName 待读文件名
   * @return
   * @throws IOException
   */
  public static String nioRead2(String fileName) throws IOException {
    long startTime = System.currentTimeMillis();
    try {
      byte[] byt = Files.readAllBytes(Paths.get(fileName));
      return new String(byt);
    } finally {
      System.out.println("使用Files.read读取文件耗时:" + (System.currentTimeMillis() - startTime) + "毫秒");
    }
  }

  public static void main(String[] args) throws IOException {
    String fileName = "E:/source.txt";
    FileRead.bioRead(fileName);
    FileRead.nioRead1(fileName);
    FileRead.nioRead2(fileName);
  }
}

2、写文件

package com.zhi.test;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;

/**
 * 文件写<br>
 * 10M的数据,BIO耗时45毫秒,NIO耗时42毫秒,Files.write耗时24毫秒
 *
 * @author 张远志
 * @since 2020年5月9日21:04:40
 *
 */
public class FileWrite {
  /**
   * 使用BIO进行文件写
   *
   * @param fileName 文件名称
   * @param content 待写内存
   * @throws IOException
   */
  public static void bioWrite(String fileName, String content) throws IOException {
    long startTime = System.currentTimeMillis();
    try {
      FileWriter writer = new FileWriter(fileName);
      writer.write(content);
      writer.close();
    } finally {
      System.out.println("使用BIO写文件耗时:" + (System.currentTimeMillis() - startTime) + "毫秒");
    }
  }

  /**
   * 使用NIO进行文件写
   *
   * @param fileName 文件名称
   * @param content 待写内存
   * @throws IOException
   */
  public static void nioWrite1(String fileName, String content) throws IOException {
    long startTime = System.currentTimeMillis();
    try {
      FileOutputStream out = new FileOutputStream(fileName);
      FileChannel channel = out.getChannel();
      ByteBuffer buf = ByteBuffer.wrap(content.getBytes());
      channel.write(buf);
      out.close();
    } finally {
      System.out.println("使用NIO写文件耗时:" + (System.currentTimeMillis() - startTime) + "毫秒");
    }
  }

  /**
   * 使用Files.write进行文件写
   *
   * @param fileName 文件名称
   * @param content 待写内存
   * @throws IOException
   */
  public static void nioWrite2(String fileName, String content) throws IOException {
    long startTime = System.currentTimeMillis();
    try {
      File file = new File(fileName);
      if (!file.exists()) {
        file.createNewFile();
      }
      Files.write(file.toPath(), content.getBytes(), StandardOpenOption.WRITE);
    } finally {
      System.out.println("使用Files.write写文件耗时:" + (System.currentTimeMillis() - startTime) + "毫秒");
    }
  }

  public static void main(String[] args) throws IOException {
    String content = FileRead.nioRead2("E:/source.txt");
    String target1 = "E:/target1.txt", target2 = "E:/target2.txt", target3 = "E:/target3.txt";
    FileWrite.bioWrite(target1, content);
    FileWrite.nioWrite1(target2, content);
    FileWrite.nioWrite2(target3, content);
  }
}

3、复制文件

package com.zhi.test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Paths;

/**
 * 文件复制<br>
 * 10M的文件,bio耗时56毫秒,nio耗时12毫秒,Files.copy耗时10毫秒
 *
 * @author 张远志
 * @since 2020年5月9日17:18:01
 *
 */
public class FileCopy {
  /**
   * 使用BIO复制一个文件
   *
   * @param target 源文件
   * @param source 目标文件
   *
   * @throws IOException
   */
  public static void bioCopy(String source, String target) throws IOException {
    long startTime = System.currentTimeMillis();
    try {
      FileInputStream fin = new FileInputStream(source);
      FileOutputStream fout = new FileOutputStream(target);

      byte[] byt = new byte[1024];
      while (fin.read(byt) > -1) {
        fout.write(byt);
      }

      fin.close();
      fout.close();
    } finally {
      System.out.println("使用BIO复制文件耗时:" + (System.currentTimeMillis() - startTime) + "毫秒");
    }
  }

  /**
   * 使用NIO复制一个文件
   *
   * @param target 源文件
   * @param source 目标文件
   *
   * @throws IOException
   */
  public static void nioCopy1(String source, String target) throws IOException {
    long startTime = System.currentTimeMillis();
    try {
      FileInputStream fin = new FileInputStream(source);
      FileChannel inChannel = fin.getChannel();
      FileOutputStream fout = new FileOutputStream(target);
      FileChannel outChannel = fout.getChannel();

      inChannel.transferTo(0, inChannel.size(), outChannel);

      fin.close();
      fout.close();
    } finally {
      System.out.println("使用NIO复制文件耗时:" + (System.currentTimeMillis() - startTime) + "毫秒");
    }
  }

  /**
   * 使用Files.copy复制一个文件
   *
   * @param target 源文件
   * @param source 目标文件
   *
   * @throws IOException
   */
  public static void nioCopy2(String source, String target) throws IOException {
    long startTime = System.currentTimeMillis();
    try {
      File file = new File(target);
      if (file.exists()) {
        file.delete();
      }
      Files.copy(Paths.get(source), file.toPath());
    } finally {
      System.out.println("使用Files.copy复制文件耗时:" + (System.currentTimeMillis() - startTime) + "毫秒");
    }
  }

  public static void main(String[] args) throws IOException {
    String source = "E:/source.txt";
    String target1 = "E:/target1.txt", target2 = "E:/target2.txt", target3 = "E:/target3.txt";
    FileCopy.bioCopy(source, target1);
    FileCopy.nioCopy1(source, target2);
    FileCopy.nioCopy2(source, target3);
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Java中BIO、NIO、AIO的理解

    在高性能的IO体系设计中,有几个名词概念常常会使我们感到迷惑不解.具体如下: 1 什么是同步? 2 什么是异步? 3 什么是阻塞? 4 什么是非阻塞? 5 什么是同步阻塞? 6 什么是同步非阻塞? 7 什么是异步阻塞? 8 什么是异步非阻塞? 先来举个实例生活中的例子: 如果你想吃一份宫保鸡丁盖饭: 同步阻塞:你到饭馆点餐,然后在那等着,还要一边喊:好了没啊! 同步非阻塞:在饭馆点完餐,就去遛狗了.不过溜一会儿,就回饭馆喊一声:好了没啊! 异步阻塞:遛狗的时候,接到饭馆电话,说饭做好了,让您亲自

  • 详解Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)

    本文会从传统的BIO到NIO再到AIO自浅至深介绍,并附上完整的代码讲解. 下面代码中会使用这样一个例子:客户端发送一段算式的字符串到服务器,服务器计算后返回结果到客户端. 代码的所有说明,都直接作为注释,嵌入到代码中,看代码时就能更容易理解,代码中会用到一个计算结果的工具类,见文章代码部分. 相关的基础知识文章推荐: Linux 网络 I/O 模型简介(图文) Java 并发(多线程) 1.BIO编程 1.1.传统的BIO编程 网络编程的基本模型是C/S模型,即两个进程间的通信. 服务端提供I

  • java高效文件流读写操作详解

    导语 防止自己以后忘记,记录一些文件流的性能对比. 平常经常会操作到文件读写,java当中提供了许多操作文件的类,一般来说,文件操作也叫流操作,可以按照以下方式分类: 按照功能分类,字节流和字符流. 按照节点流和过滤流,节点流直接操作文件,过滤流包装了节点流和过滤流.如FileInputStream和BufferedFileInputStream就是分别是节点流和过滤流. 文件流比较 下面重点比较我们经常用的几个流 (1) DataInputStream+FileInputStream (2)

  • 浅谈Java中BIO、NIO和AIO的区别和应用场景

    最近一直在准备面试,为了使自己的Java水平更上一个档次,拜读了李林峰老师的<Netty权威指南>,了解了Java关于IO的发展和最新的技术,真是受益匪浅,现在把我总结的关于BIO.NIO和AIO的区别和应用场景概述一遍. 在此之前,先弄清几个概念: 1.同步:使用同步IO时,Java自己处理IO读写. 2.异步:使用异步IO时,Java将IO读写委托给OS处理,需要将数据缓冲区地址和大小传给OS,完成后OS通知Java处理(回调). 3.阻塞:使用阻塞IO时,Java调用会一直阻塞到读写完成

  • 基于BIO的Java Socket通信详解

    BIO,即阻塞IO,在基于Socket的消息通信过程中,Socket服务端向外部提供服务,而Socket客户端可以建立到Socket服务端的连接,进而发送请求数据,然后等待Socket服务端处理,并返回处理结果(响应). 基于BIO的通信,Socket服务端会发生阻塞,即在监听过程中每次accept到一个客户端的Socket连接,就要处理这个请求,而此时其他连接过来的客户端只能阻塞等待.可见,这种模式下Socket服务端的处理能力是非常有限的,客户端也只能等待,直到服务端空闲时进行请求的处理.

  • Java中网络IO的实现方式(BIO、NIO、AIO)介绍

    在网络编程中,接触到最多的就是利用Socket进行网络通信开发.在Java中主要是以下三种实现方式BIO.NIO.AIO. 关于这三个概念的辨析以前一直都是好像懂,但是表达的不是很清楚,下面做个总结完全辨析清楚. 1. BIO方式 首先我用一个较为通俗的语言来说明: BIO 就是阻塞IO,每个TCP连接进来服务端都需要创建一个线程来建立连接并进行消息的处理.如果中间发生了阻塞(比如建立连接.读数据.写数据时发生阻碍),线程也会发生阻塞,并发情况下,N个连接需要N个线程来处理. 这种方式的缺点就是

  • java文件的重命名与移动操作实例代码

    文件的重命名与移动操作 有时候为了对文件进行统一访问与管理,需要把文件进行重命名,并移动到新的文件夹,如何实现呢? 一枚简单的java小程序即可实现: part_1:需求:我需要把<(E:\BaiduYun\传智播客_张孝祥_Java多线程与并发库高级应用视频教程下载)>文件夹下的所有子文件夹下的视频文件重命名,并移动到新的位置<(E:\BaiduYun\张孝祥_Java多线程与并发库)>; part_2:目录结构如下: E:\BaiduYun E:\BaiduYun\传智播客_张

  • Java使用BIO和NIO进行文件操作对比代码示例

    什么是Java NIO? 同步非阻塞io模式,拿烧开水来说,NIO的做法是叫一个线程不断的轮询每个水壶的状态,看看是否有水壶的状态发生了改变,从而进行下一步的操作. Java NIO有三大组成部分:Buffer,Channel,Selector,通过事件驱动模式实现了什么时候有数据可读的问题. 什么是Java BIO? 同步阻塞IO模式,数据的读取写入必须阻塞在一个线程内等待其完成.这里使用那个经典的烧开水例子,这里假设一个烧开水的场景,有一排水壶在烧开水,BIO的工作模式就是, 叫一个线程停留

  • java中BIO、NIO、AIO都有啥区别

    一.BIO(Blocking IO,也被称作old IO) 同步阻塞模型,一个客户端连接对应一个处理线程 对于每一个新的网络连接都会分配给一个线程,每隔线程都独立处理自己负责的输入和输出, 也被称为Connection Per Thread模式 缺点: 1.IO代码里read操作是阻塞操作,如果连接不做数据读写操作会导致线程阻塞,浪费资源 2.如果线程很多,会导致服务器线程太多,压力太大,比如C10K问题 所谓c10k问题,指的是服务器同时支持成千上万个客户端的问题,也就是concurrent

  • Java中BIO、NIO和AIO的区别、原理与用法

    目录 IO BIO NIO AIO 区别及联系 各自适用场景 使用方式 IO 什么是IO? 它是指计算机与外部世界或者一个程序与计算机的其余部分的之间的接口.它对于任何计算机系统都非常关键,因而所有 I/O 的主体实际上是内置在操作系统中的.单独的程序一般是让系统为它们完成大部分的工作. 在 Java 编程中,直到最近一直使用 流 的方式完成 I/O.所有 I/O 都被视为单个的字节的移动,通过一个称为 Stream 的对象一次移动一个字节.流 I/O 用于与外部世界接触.它也在内部使用,用于将

  • java Spring Boot 配置redis pom文件操作

    1.创建一个redis maven项目,在pom中添加如下信息 spring boot 版本 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.4.RELEASE</version> </parent> 项目相关jar配置 &l

  • java项目中读取jdbc.properties文件操作

    java内容 Properties props = Resources.getResourceAsProperties("jdbc.properties"); String url = props.getProperty("jdbc.url"); String driver = props.getProperty("jdbc.driverClass"); String username = props.getProperty("jdbc

  • Java中用内存映射处理大文件的实现代码

    在处理大文件时,如果利用普通的FileInputStream 或者FileOutputStream 抑或RandomAccessFile 来进行频繁的读写操作,都将导致进程因频繁读写外存而降低速度.如下为一个对比实验. package test; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOExc

  • java多线程编程同步器Future和FutureTask解析及代码示例

    publicinterfaceFuture<V>Future表示异步计算的结果.它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果.计算完成后只能使用get方法来获取结果,如有必要,计算完成前可以阻塞此方法.取消则由cancel方法来执行.还提供了其他方法,以确定任务是正常完成还是被取消了.一旦计算完成,就不能再取消计算.如果为了可取消性而使用Future但又不提供可用的结果,则可以声明Future<?>形式类型.并返回null作为底层任务的结果. Future主要

  • Java编程实现对十六进制字符串异或运算代码示例

    前言:好久没有写博客,最近一年感觉真是好忙,各种做不完的工作.相信很多上班族都会有这种感觉.最近对NFC进行写卡操作,需要计算一个校验位.一般情况下,校验位多数是由前几个字节进行异或运算所得. 现在我就先说一下我使用的场景: 把一个16字节的数据写到CPU卡(如交通卡)里面,最后一字节是校验码---前十五字节异或. 我开始从网上找了一些别人写的算法发现计算后结果不对,或者就是写的太复杂了,于是自己就写了一个,感觉也比较简单,现在分享给大家,希望一起交流一下. 第一节:什么是异或运算(主要摘自百度

  • Java利用反射获取object的属性和值代码示例

    在看反射顺便做个笔记,目前知道的反射的Object都是要有对象的也就是实体Bean. referance:Java反射简易教程 import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 反射处理Bean,得到里面的属性值 * * @author liulinsen * */ publ

随机推荐