Java IO进阶
引言: 对程序语言的设计者来说,创建一个好的输入/输出(I/O)系统是一项艰难的任务 《Thinking in Java 》
概述: Java.io 包几乎包含了所有操作输入、输出需要的类。所有这些流类代表了输入源和输出目标。java.io 包中的流支持很多种格式,比如:基本类型、对象、本地化字符集等等。一个流可以理解为一个数据的序列。输入流表示从一个源读取数据,输出流表示向一个目标写数据。Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。
Java 的 I/O 操作类在包 java.io 下,大概有将近 80 个类,但是这些类大概可以分成四组,分别是:
- 基于字节操作的 I/O 接口:InputStream 和 OutputStream
- 基于字符操作的 I/O 接口:Writer 和 Reader
- 基于磁盘操作的 I/O 接口:File
- 基于网络操作的 I/O 接口:Socket
- 新的输入/输出:NIO
本文不赘述IO的基本使用,主要记录性能测试结果和分析IO中的设计模式
一:性能测试
1.不使用缓冲流,使用FileInputStream和FileoutputStream拷贝文件
public static void main(String[] args) throws IOException { FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; try { long begin = System.currentTimeMillis(); //测试文件150MB fileInputStream = new FileInputStream(new File("C:\\Users\\Administrator\\Desktop\\深入了解计算机系统.pdf")); fileOutputStream = new FileOutputStream(new File("C:\\Users\\Administrator\\Desktop\\bb.pdf")); int len = 0; byte[] bytes = new byte[1024]; while ((len = fileInputStream.read(bytes)) != -1) { fileOutputStream.write(bytes, 0, len); } System.out.println("耗时:"+(System.currentTimeMillis()-begin));//耗时:1747 } catch (IOException e) { e.printStackTrace(); } finally { if (null != fileInputStream) { fileInputStream.close(); } if (null != fileOutputStream) { fileOutputStream.close(); } } }
2.不使用输入缓冲流,使用FileInputStream和FileoutputStream,BufferedOutputStream拷贝文件
public static void main(String[] args) throws IOException { FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; BufferedOutputStream out = null; try { long begin = System.currentTimeMillis(); //测试文件150MB fileInputStream = new FileInputStream(new File("C:\\Users\\Administrator\\Desktop\\深入了解计算机系统.pdf")); fileOutputStream = new FileOutputStream(new File("C:\\Users\\Administrator\\Desktop\\bb.pdf")); out = new BufferedOutputStream(fileOutputStream); int len = 0; byte[] bytes = new byte[1024]; while ((len = fileInputStream.read(bytes)) != -1) { out.write(bytes, 0, len); } System.out.println("耗时:"+(System.currentTimeMillis()-begin));//耗时:723 } catch (IOException e) { e.printStackTrace(); } finally { if (null != fileInputStream) { fileInputStream.close(); } if (null != out) { out.close(); } if (null != fileOutputStream) { fileOutputStream.close(); } } }
3.不使用输出缓冲流,使用FileInputStream,BufferedInputStream和FileoutputStream拷贝文件
public static void main(String[] args) throws IOException { FileInputStream fileInputStream = null; BufferedInputStream in = null; FileOutputStream fileOutputStream = null; try { long begin = System.currentTimeMillis(); //测试文件150MB fileInputStream = new FileInputStream(new File("C:\\Users\\Administrator\\Desktop\\深入了解计算机系统.pdf")); in = new BufferedInputStream(fileInputStream); fileOutputStream = new FileOutputStream(new File("C:\\Users\\Administrator\\Desktop\\bb.pdf")); int len = 0; byte[] bytes = new byte[1024]; while ((len = in.read(bytes)) != -1) { fileOutputStream.write(bytes, 0, len); } System.out.println("耗时:"+(System.currentTimeMillis()-begin));//耗时:1085 } catch (IOException e) { e.printStackTrace(); } finally { if (null != in) { in.close(); } if (null != fileInputStream) { fileInputStream.close(); } if (null != fileOutputStream) { fileOutputStream.close(); } } }
4.全部使用缓冲流,使用FileInputStream,BufferedInputStream和FileoutputStream,BufferedOutputStream拷贝文件
public static void main(String[] args) throws IOException { FileInputStream fileInputStream = null; BufferedInputStream in = null; FileOutputStream fileOutputStream = null; BufferedOutputStream out = null; try { long begin = System.currentTimeMillis(); //测试文件150MB fileInputStream = new FileInputStream(new File("C:\\Users\\Administrator\\Desktop\\深入了解计算机系统.pdf")); in = new BufferedInputStream(fileInputStream); fileOutputStream = new FileOutputStream(new File("C:\\Users\\Administrator\\Desktop\\bb.pdf")); out = new BufferedOutputStream(fileOutputStream); int len = 0; byte[] bytes = new byte[1024]; while ((len = in.read(bytes)) != -1) { out.write(bytes, 0, len); } System.out.println("耗时:"+(System.currentTimeMillis()-begin));//耗时:483 } catch (IOException e) { e.printStackTrace(); } finally { if (null != in) { in.close(); } if (null != fileInputStream) { fileInputStream.close(); } if (null != out) { out.close(); } if (null != fileOutputStream) { fileOutputStream.close(); } } }
为什么使用Buffer后,速度得到了明显,其实道理也很简单,避免的多次IO造成的资源消耗,将数据拷贝到内存缓冲区,直接从内存缓存区取数据,看看BufferedInputStream的源码就一目了然。
二:IO中用到的设计模式
在java语言 I/O库的设计中,使用了两个结构模式,即 装饰模式 和 适配器模式 。
FileInputStream fileInputStream = new FileInputStream(new File("")); fileInputStream.read(); //适配器模式 FileInputStream是字节流,而并没有字符流读取字符的一些api,因此通过InputStreamReader将其转为Reader子类,因此有了可以操作文本的文件方法。 //换句话说,就是将FileInputStream读取一个字节流的方法扩展转换为InputStreamReader读取一个字符流的功能 InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream); inputStreamReader.read(); //装饰器模式 构造了缓冲字符流,将FileInputStream字节流包装为BufferedReader过程就是装饰的过程,刚开始的字节流FileInputStream只有read一个字节的方法, //包装为inputStreamReader后,就有了读取一个字符的功能,在包装为BufferedReader后,就拥有了read一行字符的功能。 BufferedReader reader = new BufferedReader(inputStreamReader); reader.read();
附录 :常用的IO相关工具类,当然公司一般也会自己封装

=========================================================================================================================================
我只是一粒简单的石子,未曾想掀起惊涛骇浪,也不愿随波逐流
每个人都很渺小,努力做自己,不虚度光阴,做真实的自己,无论是否到达目标点,既然选择了出发,便勇往直前
我不能保证所有的东西都是对的,但都是能力范围内的深思熟虑和反复斟酌

浙公网安备 33010602011771号