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

 更新时间:2020年5月14日 08:19  点击:1498

什么是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);
  }
}

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

[!--infotagslink--]

相关文章

  • Java实现经典游戏复杂迷宫

    这篇文章主要介绍了如何利用java语言实现经典《复杂迷宫》游戏,文中采用了swing技术进行了界面化处理,感兴趣的小伙伴可以动手试一试...2022-02-01
  • php读取zip文件(删除文件,提取文件,增加文件)实例

    下面小编来给大家演示几个php操作zip文件的实例,我们可以读取zip包中指定文件与删除zip包中指定文件,下面来给大这介绍一下。 从zip压缩文件中提取文件 代...2016-11-25
  • java 运行报错has been compiled by a more recent version of the Java Runtime

    java 运行报错has been compiled by a more recent version of the Java Runtime (class file version 54.0)...2021-04-01
  • Jupyter Notebook读取csv文件出现的问题及解决

    这篇文章主要介绍了JupyterNotebook读取csv文件出现的问题及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2023-01-06
  • 在java中获取List集合中最大的日期时间操作

    这篇文章主要介绍了在java中获取List集合中最大的日期时间操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-15
  • 教你怎么用Java获取国家法定节假日

    这篇文章主要介绍了教你怎么用Java获取国家法定节假日,文中有非常详细的代码示例,对正在学习java的小伙伴们有非常好的帮助,需要的朋友可以参考下...2021-04-23
  • Java如何发起http请求的实现(GET/POST)

    这篇文章主要介绍了Java如何发起http请求的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-31
  • Photoshop打开PSD文件空白怎么解决

    有时我们接受或下载到的PSD文件打开是空白的,那么我们要如何来解决这个 问题了,下面一聚教程小伙伴就为各位介绍Photoshop打开PSD文件空白解决办法。 1、如我们打开...2016-09-14
  • 解决python 使用openpyxl读写大文件的坑

    这篇文章主要介绍了解决python 使用openpyxl读写大文件的坑,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-13
  • C#实现HTTP下载文件的方法

    这篇文章主要介绍了C#实现HTTP下载文件的方法,包括了HTTP通信的创建、本地文件的写入等,非常具有实用价值,需要的朋友可以参考下...2020-06-25
  • 浅谈Java与C#的一些细微差别

    说起C#和Java这两门语言(语法,数据类型 等),个人以为,大概有90%以上的相似,甚至可以认为几乎一样。但是在工作中,我也发现了一些细微的差别...2020-06-25
  • SpringBoot实现excel文件生成和下载

    这篇文章主要为大家详细介绍了SpringBoot实现excel文件生成和下载,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-02-09
  • C#操作本地文件及保存文件到数据库的基本方法总结

    C#使用System.IO中的文件操作方法在Windows系统中处理本地文件相当顺手,这里我们还总结了在Oracle中保存文件的方法,嗯,接下来就来看看整理的C#操作本地文件及保存文件到数据库的基本方法总结...2020-06-25
  • php无刷新利用iframe实现页面无刷新上传文件(1/2)

    利用form表单的target属性和iframe 一、上传文件的一个php教程方法。 该方法接受一个$file参数,该参数为从客户端获取的$_files变量,返回重新命名后的文件名,如果上传失...2016-11-25
  • php批量替换内容或指定目录下所有文件内容

    要替换字符串中的内容我们只要利用php相关函数,如strstr,str_replace,正则表达式了,那么我们要替换目录所有文件的内容就需要先遍历目录再打开文件再利用上面讲的函数替...2016-11-25
  • 解决Java处理HTTP请求超时的问题

    这篇文章主要介绍了解决Java处理HTTP请求超时的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-29
  • PHP文件上传一些小收获

    又码了一个周末的代码,这次在做一些关于文件上传的东西。(PHP UPLOAD)小有收获项目是一个BT种子列表,用户有权限上传自己的种子,然后配合BT TRACK服务器把种子的信息写出来...2016-11-25
  • Zend studio文件注释模板设置方法

    步骤:Window -> PHP -> Editor -> Templates,这里可以设置(增、删、改、导入等)管理你的模板。新建文件注释、函数注释、代码块等模板的实例新建模板,分别输入Name、Description、Patterna)文件注释Name: 3cfileDescriptio...2013-10-04
  • AI源文件转photoshop图像变模糊问题解决教程

    今天小编在这里就来给photoshop的这一款软件的使用者们来说下AI源文件转photoshop图像变模糊问题的解决教程,各位想知道具体解决方法的使用者们,那么下面就快来跟着小编...2016-09-14
  • java 判断两个时间段是否重叠的案例

    这篇文章主要介绍了java 判断两个时间段是否重叠的案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-15