天天看点

java学习笔记16--I/O流和文件

io流用来处理设备之间的数据传输,对数据的操作是通过流的方式,java用于操作流的对象都在io包中

输入/输出流可以从以下几个方面进行分类

从流的方向划分:

输入流、输出流

从流的分工划分:

节点流、处理流

从流的内容划分:

面向字符的流、面向字节的流

字符流和字节流

字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。 字节流和字符流的区别:

读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。

处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。

结论:只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。

流按流向分为:输入流、输出流

字节流的抽象基类:

•inputstream,outputstream。

字符流的抽象基类:

•reader, writer。

注:由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。

如:inputstream的子类fileinputstream。

如:reader的子类filereader。

java流操作有关的类或接口:

java学习笔记16--I/O流和文件

java流类图结构:

java学习笔记16--I/O流和文件

 写文本文件

例:在c盘根目录创建文本文件hello.txt,并往里写入若干行文本

说明:

每次运行这个程序,都将删除已经存在的”hello.txt”文件,创建一个新的同名文件。filewriter的构造方法有五个,本例是通过一个字符串指定文件名来创建。filewriter类的write方法向文件中写入字符

writer类的流可实现内部格式到外部磁盘文件格式的转换

“hello.txt”是一个普通的ascii码文本文件,每个英文字符占一个字节,中文字符占两个字节

java程序中的字符串则是每个字符占两个字节的,采用unicode编码

java学习笔记16--I/O流和文件

close方法清空流里的内容并关闭它。如果不调用该方法,可能系统还没有完成所有数据的写操作,程序就结束了

在看一个例子:处理io异常

说明:

运行此程序,会发现在原文件内容后面又追加了重复的内容,这就是将构造方法的第二个参数设为true的效果

如果将文件属性改为只读属性,再运行本程序,就会出现io错误,程序将转入catch块中,给出出错信息

bufferedwriter类

如果需要写入的内容很多,就应该使用更为高效的缓冲器流类bufferedwriter

filewriter和bufferedwriter类都用于输出字符流,包含的方法几乎完全一样,但bufferedwriter多提供了一个newline()方法用于换行

使用bufferedwriter完成上面的功能:

读文本文件

filereader类

从文本文件中读取字符

继承自reader抽象类的子类inputstreamreader

bufferedreader

读文本文件的缓冲器类

具有readline()方法,可以对换行符进行鉴别,一行一行地读取输入流中的内容

继承自reader

文件输入方法:

java学习笔记16--I/O流和文件

从hello.txt中读取文本并显示在屏幕上

运行该程序,屏幕上将逐行显示出hello.txt文件中的内容

filereader对象:创建后将打开文件,如果文件不存在,会抛出一个ioexception

bufferedreader类的readline()方法:从一个面向字符的输入流中读取一行文本。如果其中不再有数据,返回null

reader类的read()方法:也可用来判别文件结束。该方法返回的一个表示某个字符的int型整数,如果读到文件末尾,返回 -1。据此,可修改本例中的读文件部分:

close()方法:为了操作系统可以更为有效地利用有限的资源,应该在读取完毕后,调用该方法

指定源文件和目标文件名,将源文件的内容拷贝至目标文件。调用方式为:

java copy sourcefile  destinationfile

java学习笔记16--I/O流和文件

二进制文件

原则上讲,所有文件都是由8位的字节组成的

如果文件字节中的内容应被解释为字符,则文件被称为文本文件;如果被解释为其它含义,则文件被称为二进制文件

例如文字处理程序,例如字处理软件word产生的doc文件中,数据要被解释为字体、格式、图形和其他非字符信息。因此,这样的文件是二进制文件,不能用reader流正确读取

为什么需要二进制文件?

输入输出更快

比文本文件小很多

有些数据不容易被表示为字符

抽象类outputstream

派生类fileoutputstream

用于一般目的输出(非字符输出)

用于成组字节输出

派生类dataoutputstream

具有写各种基本数据类型的方法

将数据写到另一个输出流

它在所有的计算机平台上使用同样的数据格式

其常用的一些方法见下表

java学习笔记16--I/O流和文件
java学习笔记16--I/O流和文件

例:将三个int型数字255/0/-1写入数据文件data1.dat

fileoutputstream类的构造方法负责打开文件“data1.dat”用于写数据

fileoutputstream类的对象与dataoutputstream对象连接,写基本类型的数据

bufferedoutputstream

写二进制文件的缓冲流类

类似于文本文件中的bufferedwriter

对于大量数据的写入,可提高效率

用法示例:

例:向文件中写入各种数据类型的数,并统计写入的字节数

读二进制文件

过滤流

读或写的同时对数据进行处理

通过另外一个流来构造一个过滤流

大部分java.io 包所提供过滤流都是filterinputstream和filteroutputstream的子类:

datainputstream 和 dataoutputstream

bufferedinputstream 和 bufferedoutputstream

linenumberinputstream

pushbackinputstream

printstream

读取上面的例子创建的数据文件中的3个int型数字,显示相加结果

分析:

readint方法可以从输入流中读入4个字节并将其当作int型数据

由于知道文件中存储的是3个int型数据,所以使用了3个读入语句

如果不知道数据的个数该怎么办呢?因为datainputstream的读入操作如遇到文件结尾就会抛出eofexception异常,所以我们可以将读操作放入try块中

将读操作放入try块中,使遇到文件结尾就会抛出eofexception异常,进入到相应的catch块中

表示磁盘文件信息

定义了一些与平台无关的方法来操纵文件

–创建、删除文件

–重命名文件

–判断文件的读写权限及是否存在

–设置和查询文件的最近修改时间等

构造文件流可以使用file类的对象作为参数

file类常用方法:

java学习笔记16--I/O流和文件
java学习笔记16--I/O流和文件

例:在c盘创建文件hello.txt,如果存在则删除旧文件,不存在则直接创建新的

压缩流类

–java.util.zip包中提供了一些类,使我们可以以压缩格式对流进行读写

–它们都继承自字节流类outputstream和inputstream

–其中gzipoutputstream和zipoutputstream可分别把数据压缩成gzip格式和zip格式

–gzipinputstream和zipinputstream可以分别把压缩成gzip格式或zip的数据解压缩恢复原状

zip文件

–可能含有多个文件,所以有多个入口(entry)

–每个入口用一个zipentity对象表示,该对象的getname()方法返回文件的最初名称

zipoutputstream

–父类是deflateroutputstream

–可以把数据压缩成zip格式

zipinputstream

–父类是inflaterinputstream

–可以把压缩成zip格式的数据解压缩

例:指定若干文件名,将所有文件压缩为"c:/test.zip",再从此压缩文件中解压缩并显示

再看一个例子:解压缩zip文件,并恢复其原来路径

保存对象的信息,在需要的时候,再读取这个对象

内存中的对象在程序结束时就会被垃圾回收机制清除

用于对象信息存储和读取的输入输出流类:

objectinputstream、objectoutputstream

实现对象的读写

通过objectoutputstream把对象写入磁盘文件

通过objectinputstream把对象读入程序

–不保存对象的transient和static类型的变量

–对象要想实现序列化,其所属的类必须实现serializable接口

必须通过另一个流构造objectoutputstream:

必须通过另一个流构造objectinputstream:

空接口,使类的对象可实现序列化

serializable 接口的定义:

实现serializable接口的语句

使用关键字transient可以阻止对象的某些成员被自动写入文件

看一个例子:

创建一个书籍对象,并把它输出到一个文件book.dat中,然后再把该对象读出来,在屏幕上显示对象信息

externalizable 接口

–实现该接口可以控制对象的读写

–api中的说明为

–其中有两个方法writeexternal()和readexternal(),因此实现该接口的类必须实现这两个方法

–objectoutputstream的writeobject()方法只写入对象的标识,然后调用对象所属类的writeexternal()

–objectinputstream的readobject()方法调用对象所属类的readexternal()

randomaccessfile类

–可跳转到文件的任意位置读/写数据

–可在随机文件中插入数据,而不破坏该文件的其他数据

–实现了datainput 和 dataoutput 接口,可使用普通的读写方法

–有个位置指示器,指向当前读写处的位置。刚打开文件时,文件指示器指向文件的开头处。对文件指针显式操作的方法有:

int skipbytes(int n):把文件指针向前移动指定的n个字节

void seek(long):移动文件指针到指定的位置。

long getfilepointer():得到当前的文件指针。

–在等长记录格式文件的随机读取时有很大的优势,但仅限于操作文件,不能访问其它io设备,如网络、内存映像等

–可用来实现读和写,构造方法包括

–建立一个randomaccessfile时,要指出你要执行的操作:仅从文件读,还是同时读写

randomaccessfile类常用api

java学习笔记16--I/O流和文件

例:创建一个雇员类,包括姓名、年龄。姓名不超过8个字符,年龄是int类型。每条记录固定为20个字节。使用randomaccessfile向文件添加、修改、读取雇员信息