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

作者:玄同太子 时间:2023-04-18 16:14:21 

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

来源:https://www.cnblogs.com/zhi-leaf/p/12860192.html

标签:Java,BIO,NIO,文件,操作
0
投稿

猜你喜欢

  • Android Camera1实现预览框显示

    2021-11-03 20:04:20
  • 在Eclipse安装Spring boot插件的步骤(图文)

    2023-01-14 05:04:05
  • Java Zookeeper分布式分片算法超详细讲解流程

    2023-07-08 06:56:36
  • springboot 同时启用http/https的配置方法

    2023-06-22 12:04:12
  • unity3D实现摄像机抖动特效

    2022-09-20 12:10:42
  • C#线程间通信的异步机制

    2023-10-13 16:45:23
  • C#反射内存的处理分析

    2022-04-30 00:56:22
  • UnityShader使用图像叠加实现运动模糊

    2021-09-24 14:45:16
  • 深入浅析SpringBoot自动配置原理

    2022-11-19 01:49:24
  • Java日常练习题,每天进步一点点(58)

    2021-06-26 01:13:02
  • Kotlin Flow数据流的3种使用场景详解

    2021-06-03 09:06:18
  • android播放器实现歌词显示功能

    2021-10-27 13:44:37
  • java实现简单年龄计算器

    2022-01-28 02:23:34
  • 详解Java的MyBatis框架与Spring框架整合中的映射器注入

    2021-06-02 00:32:31
  • java8新特性将List中按指定属性排序过滤重复数据的方法

    2023-06-16 17:57:42
  • Android App开发中使用RecyclerView替代ListView的实践

    2021-06-14 06:53:36
  • C#基础知识之this关键字介绍

    2022-02-08 10:59:16
  • Java实现线程安全单例模式的五种方式的示例代码

    2023-09-26 16:41:23
  • Java中方法的使用、重载与递归的详细介绍

    2022-03-02 02:50:05
  • Android TagCloudView云标签的使用方法

    2023-03-28 14:29:20
  • asp之家 软件编程 m.aspxhome.com