2.文件的读写

2.文件的读写

程序将要存储的数据输出到文件叫作“写”。程序要处理文件的内容,必须先将文件的内容输入到内存,这个过程叫作“读”。用Java进行文件的输入输出是通过引用java.io包中的类来实现的。

在Java中,内存和外设(或者其他外设)之间的数据传递被看作沿着数据序列依次顺序的“流”,如图2.10.1所示。io包中各种不同的“流”类大体上按照两种方式来分类:一是按照数据的处理单位(是字节还是字符);二是按照输入、输出的方向。

图2.10.1 内存和外存之间的数据传递

以Stream结尾的类是字节流,以字节为处理单位,主要用于二进制文件的读写,如整型或浮点等类型的数据、文本、图片、音乐、视频等。以InputStream结尾的类是字节输入流,以OutputStream结尾的类是字节输出流。

以Reader结尾的类是字符输入流,以Writer结尾的是字符输出流。字符流用于以字符为单位的文本文件的读写。这里的聊天历史文件就是文本文件,所以用字符流来处理。

本质上,任何数据在计算机存储中都是二进制的,所以,字节流可以处理所有类型的文件,而字符流将每两个字节组合为一个字符,以字符作为单位,这样对字符文件处理起来更方便。

InputStream、OutputStream、Reader、Writer这4个类将“流”类划分为四大类:字节输入流、字节输出流、字符输入流、字符输出流。这4个类是一系列具体输入输出流的基类,是子类的模板,规定了下层各“流”类需要提供的统一的可调用的API,但是这4个类不能创建实际的对象,也不能用来作为实际的输入输出,它们是抽象类。io包中的“流”类是比较多的,学习的时候,要注意分类和分层,先在结构上把握类之间的关系和区别,然后再了解类的使用细节。

这里提到抽象类的概念,我们通过一个现实中的例子来理解:把交通工具分为陆路工具、飞行工具、水路工具,这3个都是抽象概念(抽象类),规定了每种工具的主要特征,而可以实际采用的是它们的某种非抽象子类,例如,陆路工具的子类有汽车、火车、自行车等,飞行工具的子类有飞机、火箭、热气球等,水路工具的子类有轮船、木舟、潜水艇等。

我们先来看读写聊天历史文件的方法,聊天文件是文本文件,所以用字符流。在字符流里面的FileReader和FileWriter是可以直接和文件相联的。

fr和fw是字符流对象,是以字符为单位的。我们在聊天时希望一行一行地输入和输出,而缓存流提供了一次输入输出一行的方法,所以以fr和fw为参数创建输入输出的字符缓存流。

这样,br.read Line()就可以一次读入一行,pw.println(“hello”)就可以一次写出一行。这里的Buffered Reader流和Buffered Writer流是不能直接和外设文件相联的,需要先通过FileReader和FileWriter和外设文件相联。这里是“装饰器设计模式”的一种应用,大家可以自行了解。