Java的IO类都在java.io包下,这些类大致可分为以下4种:

  1. 基于字节操作的 I/O 接口:InputStream 和 OutputStream
  2. 基于字符操作的 I/O 接口:Writer 和 Reader
  3. 基于磁盘操作的 I/O 接口:File
  4. 基于网络操作的 I/O 接口:Socket

1 IO类库的基本结构

1.1 基于字节操作的IO接口

  基于字节操作的IO接口分别是InputStream和OutputStream,InputStream的类结构图如下所示:

  同InputStream类似,OutputStream类也有着相同的类结构图。

  关于各个子类的使用可以参考JDK 的 API 说明文档,这里我们需要注意的是:操作数据的方式是可以组合的,如下所示:

InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("h:\\haha.txt"), "utf-8");

  从上面代码可以看出,InputStreamReader可以从FileInputStream中读取数据,从源码中可以看出来,其实不仅是InputStreamReader,所有的IO类都可以以这种方式来组合使用。

  还有一点需要注意的是必须制定流最终写入到什么地方,是磁盘还是网络,从OutputStream类图中可以看出,写入网络中实际也是写文件操作,只不过底层是通过网络传输了。

1.2 基于字符的IO操作接口

   不管是磁盘还是网络数据传输,都是以字节为单位的,但是程序中一般常见的数据操作都是以字符为单位的(Java中char占用2字节,C/C++中 char占用1字节),这就需要我们有一个操作字符的IO接口,来处理字符与字节见的编码转换问题,也就是Write和Reader接口及其实现类,他们 二者的类接口图如下:

  读字符接口Reader的最主要操作方法为read(),其读取字符并返回读取的字符数,不管是 Writer 还是 Reader 类它们都只定义了读取或写入的数据字符的方式,也就是怎么写或读,但是并没有规定数据要写到哪去(比如磁盘或者网络)。

1.3 字节与字符的转化接口

  有时数据持久化和网络传输是以字节进行的,所有需要字节和字符之间的相互转换。

 

/**
* 使用FileReader进行读取文件
*/
@Test
public void testFileReader() throws IOException {
FileReader fileReader = new FileReader("h:\\haha.txt");
char[] buff = new char[512];
StringBuffer stringBuffer = new StringBuffer(); while (fileReader.read(buff) > 0) {
stringBuffer.append(buff);
}
fileReader.close(); System.out.print(stringBuffer.toString());
} /**
* 使用FileReader进行读取文件,然后FileWriter写入另一个文件
*/
@Test
public void testFileReaderAndFileWriter() throws IOException {
FileReader fileReader = new FileReader("h:\\haha.txt");
char[] buff = new char[512];
StringBuffer stringBuffer = new StringBuffer(); while (fileReader.read(buff) > 0) {
stringBuffer.append(buff);
}
System.out.println(stringBuffer.toString()); FileWriter fileWriter = new FileWriter("h:\\haha2.txt");
fileWriter.write(stringBuffer.toString().trim()); fileWriter.close();
System.out.println("写入文件成功");
}
/**
* 使用InputStreamReader进行读取文件
*/
@Test
public void testInputStreamReader() throws IOException {
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("h:\\haha.txt"), "utf-8");
char[] buff = new char[512];
StringBuffer stringBuffer = new StringBuffer(); while (inputStreamReader.read(buff) > 0) {
stringBuffer.append(buff);
}
System.out.println(stringBuffer.toString());
} @Test
public void testIntputStream2() throws IOException {
InputStreamReader inputStreamReader = new InputStreamReader(new StringBufferInputStream("hello world"));
char[] buff = new char[512]; int n = inputStreamReader.read(buff);
System.out.println(n);
System.out.println(buff);
} /**
* 使用inputStreamReader进行读取文件,然后OutputStreamWriter写入另一个文件
*/
@Test
public void testOutputStreamWriter() throws IOException {
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("h:\\haha.txt"), "utf-8");
char[] buff = new char[512];
StringBuffer stringBuffer = new StringBuffer(); while (inputStreamReader.read(buff) > 0) {
stringBuffer.append(buff);
}
System.out.println(stringBuffer.toString()); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("h:\\haha2.txt"), "utf-8");
outputStreamWriter.write(stringBuffer.toString().trim());
outputStreamWriter.close();
}

  注意:FileReader类继承了InputStreamReader,FileReader读取文件流,通过StreamDecoder解码成char,其解码字符集使用的是默认字符集。在Java中,我们应该使用File对象来判断某个文件是否存在,如果我们用FileOutputStream或者FileWriter打开,那么它肯定会被覆盖。

2 同步和异步、阻塞和非阻塞

  同步和异步是针对IO来说的。所谓同步就是一个任务的完成需要依赖另外一个任务时,只有等待被依赖的任务完成后,依赖的任务才能算完成,这是一种可靠的任务序列。要么成功都成功,失败都失败,两个任务的状态可以保持一致。而异步是不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也立即执行,只要自己完成了整个任务就算完成了。至于被依赖的任务最终是否真正完成,依赖它的任务无法确定,所以它是不可靠的任务序列。我们可以用打电话和发短信来很好的比喻同步与异步操作。

  阻塞和非阻塞是针对CPU来说的。阻塞与非阻塞主要是从 CPU 的消耗上来说的,阻塞就是 CPU 停下来等待一个慢的操作完成 CPU 才接着完成其它的事。非阻塞就是在这个慢的操作在执行时 CPU 去干其它别的事,等这个慢的操作完成时,CPU 再接着完成后续的操作。虽然表面上看非阻塞的方式可以明显的提高 CPU 的利用率,但是也带了另外一种后果就是系统的线程切换增加。增加的 CPU 使用时间能不能补偿系统的切换成本需要好好评估。

3 序列化

  Java的对象序列化将那些实现了Serializable接口的对象转换成一个字节序列,并能够在以后将这个字节序列完全恢复为原来的对象。这一过程可通过网络进行,这样序列化机制能够自动弥补不同操作系统之间的差异。对应序列化的聪明之处在于它不仅保存了对象的“全景图”,而且能够追踪到对象自所包含的引用,并保存这些对象;接着又能够对对象内包含的每个这样的引用进行最终;以此类推。

  要实例化一个对象,首先创建某些OutputStream对象,然后将其封装在一个ObjectOutputStream对象内,这是,只需要调用writeObject()即可将对象序列化,并将其发送到OutputStream(对象序列化基于字节,因此使用InputStream和OutputStream继承类层次结构)。反序列化和序列化过程正好相反,需要将一个InputStream封装在ObjectInputStream内,然后调用readObject()获取一个引用,它指向一个向上转型的Object,所以必须向下转型才能直接设置它们。下面是序列化和反序列化示例代码:

@Test
public void testWriteSerialization() {
try {
FileOutputStream fileOutputStream = new FileOutputStream("h:\\serialize.txt");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); objectOutputStream.writeObject("start");
objectOutputStream.writeObject(new Person("luoxn28", 23));
objectOutputStream.writeObject(12);
objectOutputStream.close(); } catch (IOException e) {
e.printStackTrace();
} System.out.println("end...");
} @Test
public void testReadSerialization() {
try {
FileInputStream fileInputStream = new FileInputStream("h:\\serialize.txt");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
String info1 = (String) objectInputStream.readObject();
Person person = (Person) objectInputStream.readObject();
int num = (int) objectInputStream.readObject(); System.out.println(info1);
System.out.println(person);
System.out.println(num); } catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}

参考资料:

  1、深入分析 Java I/O 的工作机制

  2、Java IO系统

Java IO工作机制分析的更多相关文章

  1. Java 类反射机制分析

    Java 类反射机制分析 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某 ...

  2. Java 动态代理机制分析及扩展

    Java 动态代理机制分析及扩展,第 1 部分 王 忠平, 软件工程师, IBM 何 平, 软件工程师, IBM 简介: 本文通过分析 Java 动态代理的机制和特点,解读动态代理类的源代码,并且模拟 ...

  3. Java 动态代理机制分析及扩展,第 1 部分

    Java 动态代理机制分析及扩展,第 1 部分 http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/ 本文通过分析 Java 动态代理的机制和特 ...

  4. 磁盘IO工作机制

    磁盘IO工作机制 ref: <深入分析java web 技术内幕> by:许令波 几种访问文件的方式 文件读取和写入的 IO 操作都是调用操作系统提供的接口,因为磁盘设备是由操作系统管理的 ...

  5. [转]Java 动态代理机制分析及扩展

    引言 Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执 ...

  6. Java 动态代理机制分析及扩展--转

    http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/#icomments http://www.ibm.com/developerworks/c ...

  7. 网络 IO 工作机制

    ref: 深入分析 java web 技术内幕 2.3 两台计算机之间进行数据的传输需要经过很多步骤.首先有相互沟通的意向,然后还要有沟通的通道:通过电话还是面对面交流(物理链路).最后,两个人说话的 ...

  8. Java IO设计模式彻底分析 (转载)

    一.引子(概括地介绍Java的IO) 无论是哪种编程语言,输入跟输出都是重要的一部分,Java也不例外,而且Java将输入/输出的功能和使用范畴做了很大的扩充.它采用了流的 机制来实现输入/输出,所谓 ...

  9. Java垃圾回收机制分析

    Java的堆是一个运行时数据区,类的实例从中分配空间,堆中存储着正在运行的应用程序所建立的所有对象.垃圾回收是一种动态存储管理技术.它按照特定的垃圾回收算法,自动释放掉不再被引用的对象.堆内存里垃圾的 ...

随机推荐

  1. IIS8 添加配置 WCF服务

    今天在Windows8.1 操作系统部署了半天的WCF 一直老是在报错.在这里做个记录 防止下次忘记 在网上查了半天.终于知道原来IIS8不支持WCF服务SVC的请求.所以必须要给IIS8添加WCF服 ...

  2. CSS3梅花三弄特效

    效果预览:http://hovertree.com/texiao/js/22/ 效果图: 代码如下: <html> <head> <meta http-equiv=&qu ...

  3. 总结shell

    总结shell里面一些初学者不容易懂得点,因为我本身就是初学者,所以有一些知识点是不容易通过字面意思理解的,下面写在这里. (便于理解的一个方法就是举例子)举个例子就是哪些容易学,哪些不容易理解:丁是 ...

  4. html&css中的文字对齐问题

    html&css的使用过程中,我们经常会遇到很多文字对齐问题.下面我要介绍一个有丁点难的文字对齐问题. 实现效果如下图所示.   两行长度不定的文字,要让它们总体水平居中,然后,这两行字要左对 ...

  5. 通过HttpListener实现简单的Http服务

    使用HttpListener实现简单的Http服务 HttpListener提供一个简单的.可通过编程方式控制的 HTTP 协议侦听器.使用它可以很容易的提供一些Http服务,而无需启动IIS这类大型 ...

  6. FIS3的简单使用

    序言: 最近在收集前端的优化工具,随便一搜,厉害了word哥,有grunt.gulp.FIS3.webpack等等,简直就是眼花缭乱!前辈们对于他们的评价各有千秋,于是乎就想每个都来用一遍(之前已经倒 ...

  7. sharepoint2013的审核日志的时间区域设置

    最近在项目中碰到审核日志的时间为GMT格式 ,如何格式化成本地时间. 网站集设置成本地区域无法解决此类问题,后来查询资料才知道.无法更改 Change Audit Time From GMT Time ...

  8. SharePoint 2013 必备组件之 Windows Server AppFabric 安装错误

    1.如下图,在使用SharePoint2013产品准备工具的时候,网上下载安装Windows Server AppFabric的时候,报错,点击完成重启计算机,重新安装依然报错. 2.无奈之下,只有选 ...

  9. Android Fragment使用(二) 嵌套Fragments (Nested Fragments) 的使用及常见错误

    嵌套Fragment的使用及常见错误 嵌套Fragments (Nested Fragments), 是在Fragment内部又添加Fragment. 使用时, 主要要依靠宿主Fragment的 ge ...

  10. Touch ID使用

    前言:如果图片看不了请移步:简书 Touch ID简介 Touch ID指纹识别作为iPhone 5s上的"杀手级"功能早已为人们所熟知,目前搭载的设备有iphone SE.iPh ...