Java I/O 概述---文件读写总结
2015-08-17 00:02
746 查看
以前写Java读写文件的代码,基本上都是到处拷贝,没有深入研究过。以至于有段时间都搞不清楚,使用完一个File对象时候,要不要close。最近写了一些代码也看了一些文章,现在把掌握的I/O知识梳理一下,以备有序补充扩展。
字节流:图片、视频文件中存储的都是二进制的字节(byte)。直观的想法,读取的时候当前是按照byte逐个读取。
不管是文本、还是图书、视频最终在磁盘上的时候都是按照byte存储的。因此,可以想象Java要提供基于字符流的机制,就要处理字节和字符的相互转化,这里又涉及字符集合字符编码的问题。
Java中的输入输出都是以内存为参考的,即往内存里写,叫输入(input);从内存里读,叫输出(output)。至于为什么以内存为参考,我的理解是内存是与计算(即CPU)强相关的,最终的目录是以计算为核心,也就是以处理问题为核心。
FileReader和FileWriter的基本使用很简单,上面是简单的实例代码。我以前的疑惑是:创建FileReader对象的时候到底要不要创建File对象?因为创建FileReader对象的时候有下面两张方式:
是不是传入字符串就不用创建对象,效率更高呢?看了JDK源码终于知道,其实是一样的。直接传入字符传的时候,Java内部其实会new一个File对象的。
字节流(FileInputStream和FileOutputStream)
FileInputStream和FileOutputStream基本用法也很简单,下面是实例代码。
带缓冲的读写(BufferedReader/BufferWriter/BufferInputStream/BufferedOutputStream)
读写磁盘是比较耗时的操作,试想如果每次读写一个字节或字符都进行一次磁盘I/O,那性能一定低的吓人。比较直观的方法当然是,一次读写一批数据。Buffered就是用来解决这个问题的。
BufferedReader/BufferWriter对应FileReader/FileWriter
BufferedInputStream/BufferedOutputStream对应FileInputStream/FileOutputStream
基本用法,如实例代码。
BufferedReader是如何实现缓冲的呢?也就是按块读取。内部使用了一个byte数组,数组大小默认为8192。每次从磁盘读取多个字节,内部做标记,如果读完了,则进行读取。另外,讲的Java I/O的时候,一般都会讲的装饰模式。太多了,后面再补吧。
流的关闭:
基本原则,谁申请、谁关闭。
例如:Properties.load如果传入的是一个inputStream,谁来负责关闭它?
props.load是不会关闭流的,因此应该由流的创建者来关闭。
参考文章:
https://docs.oracle.com/javase/tutorial/essential/io/
http://davidisok.iteye.com/blog/2106489
http://stackoverflow.com/questions/3991577/closing-java-inputstreams
一、Java I/O概述
先放一张图,对Java I/O有个总统的认识。从这张图可以很清楚的看清Java I/O的整体情况。大的方面分两类:字节流和字符流。然后就是输入和输出。1.1 什么是流
记得当初上学的时候,第一次遇到stream的概念就懵了。什么是流?现在好像也不是很明白。现留着吧,占个坑,等明白了再补。1.2 字节流和字符流
字符流:一般文本文件中存放都是有明确含义的,可供人阅读理解的字符(char)。使用程序读取文件的就希望可以按照字符逐个读取。字节流:图片、视频文件中存储的都是二进制的字节(byte)。直观的想法,读取的时候当前是按照byte逐个读取。
不管是文本、还是图书、视频最终在磁盘上的时候都是按照byte存储的。因此,可以想象Java要提供基于字符流的机制,就要处理字节和字符的相互转化,这里又涉及字符集合字符编码的问题。
1.3 输出和输出
这个问题看着简单,可是又很长一段时间都没搞清楚。这里的根本问题就是以谁作为参考。参考系定了,input、output就不会搞混了。Java中的输入输出都是以内存为参考的,即往内存里写,叫输入(input);从内存里读,叫输出(output)。至于为什么以内存为参考,我的理解是内存是与计算(即CPU)强相关的,最终的目录是以计算为核心,也就是以处理问题为核心。
二、I/O的使用的文件读写
字符流(FileReader和FileWriter)
public static void copyByChar() { FileReader fileReader = null; FileWriter fileWriter = null; try { fileReader = new FileReader(DATA_FILE_NAME); fileWriter = new FileWriter(OUTPUT_FILE_NAME); int value; while((value = fileReader.read()) != -1) { System.out.println(value); fileWriter.write(value); } } catch(Exception e) { e.printStackTrace(); } finally { try { fileReader.close(); fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } }
FileReader和FileWriter的基本使用很简单,上面是简单的实例代码。我以前的疑惑是:创建FileReader对象的时候到底要不要创建File对象?因为创建FileReader对象的时候有下面两张方式:
FileReader fileReaderByStream = new FileReader("d:\\test.txt"); FileReader fileReaderByFile = new FileReader(new File("d:\\test.txt"));
是不是传入字符串就不用创建对象,效率更高呢?看了JDK源码终于知道,其实是一样的。直接传入字符传的时候,Java内部其实会new一个File对象的。
字节流(FileInputStream和FileOutputStream)
public static void copyByByte() { FileInputStream inStream = null; FileOutputStream outStream = null; try { inStream = new FileInputStream(DATA_FILE_NAME); outStream = new FileOutputStream(OUTPUT_FILE_NAME); int value; while((value = inStream.read()) != -1) { System.out.print(value); outStream.write(value); } } catch (Exception e) { e.printStackTrace(); } finally { try { inStream.close(); outStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
FileInputStream和FileOutputStream基本用法也很简单,下面是实例代码。
带缓冲的读写(BufferedReader/BufferWriter/BufferInputStream/BufferedOutputStream)
读写磁盘是比较耗时的操作,试想如果每次读写一个字节或字符都进行一次磁盘I/O,那性能一定低的吓人。比较直观的方法当然是,一次读写一批数据。Buffered就是用来解决这个问题的。
BufferedReader/BufferWriter对应FileReader/FileWriter
BufferedInputStream/BufferedOutputStream对应FileInputStream/FileOutputStream
基本用法,如实例代码。
public static void copyWithBuffer() { BufferedReader bufferedReader = null; BufferedWriter bufferedWriter = null; try { bufferedReader = new BufferedReader(new FileReader(DATA_FILE_NAME)); bufferedWriter = new BufferedWriter(new FileWriter(OUTPUT_FILE_NAME)); int value; while((value = bufferedReader.read()) != -1) { System.out.println(value); bufferedWriter.write(value); } } catch(Exception e) { e.printStackTrace(); } finally { try { bufferedReader.close(); bufferedWriter.close(); } catch (IOException e) { e.printStackTrace(); } } }
BufferedReader是如何实现缓冲的呢?也就是按块读取。内部使用了一个byte数组,数组大小默认为8192。每次从磁盘读取多个字节,内部做标记,如果读完了,则进行读取。另外,讲的Java I/O的时候,一般都会讲的装饰模式。太多了,后面再补吧。
流的关闭:
基本原则,谁申请、谁关闭。
Properties props = new Properties(); try { props.load(new FileInputStream("message.properties")); //omitted. } catch (Exception ex) {}
例如:Properties.load如果传入的是一个inputStream,谁来负责关闭它?
props.load是不会关闭流的,因此应该由流的创建者来关闭。
// create and load default properties Properties defaultProps = new Properties(); FileInputStream in = new FileInputStream("defaultProperties"); defaultProps.load(in); in.close();
参考文章:
https://docs.oracle.com/javase/tutorial/essential/io/
http://davidisok.iteye.com/blog/2106489
http://stackoverflow.com/questions/3991577/closing-java-inputstreams
相关文章推荐
- 10种Java开发者编写SQL语句时常见错误
- 因酷Java版开源网校系统,轻松实现线下到线上的转变
- Java爬取网页
- Java实现邮件发送
- Java用SAX解析XML
- 疯狂java——面向对象
- 如何在 OS X Yosemite 中安装 Java
- Spring3.0+Struts2.2+Hibernate3.6整合与常见问题
- 【每周一讲】Java的ThreadLocal
- 对象初始化都做了什么
- Spring Aop实例
- Spring Aop详尽教程
- 开发java程序的基本步骤:程序的编译与运行
- Java-拾遗:接口
- 8.16 myeclipse乱码发布覆盖问题
- Maven+Spring MVC+MyBatis+dbpc+Mysql Web项目构建
- Java JUC之Atomic系列12大类实例讲解和原理分解
- 【java编程思想--学习笔记(四)】对象导论
- SpringMVC Controller 介绍
- 黑马程序员——枚举(JDK5的新特性)