java之IO
- 什么是数据流?
- 四个抽象类?
- 输入数据流
- 主要数据操作方法
- 输出数据流
- 操作方法
- 文件数据流
- 过滤器数据流
- 缓冲区数据流创建方式
- 数据数据流
- 创建方式
- 三个文件流的区别
- 对象流
- 序列化
- 字符流操作,读者和写者
- 缓冲区读者和缓冲区写者
- file类
- 相关方法
- 随机访问文件
- 目录工具
- 总结
什么是数据流?
数据流是指一组有顺序的、有起点和终点的字节集合。
四个抽象类?
InputStream、OutputStream、Reader、Writer
由java.io包中提供,此外,包中还有其他常用的数据流,因此在涉及数据流操作的程序中,几乎都要使用引入语句:
import java.io.*;
字节流:一次读入或读出是8位二进制。
字符流:一次读入或读出是16位二进制。
数据流分为输入数据流和输出数据流。输入数据流只能读不能写,而输出数据流只能写不能读。从数据流中读取数据时,必须有一个数据源与该数据流相连。
最初的版本中,java.io包中的流只有普通的字节流,即以byte为基本处理单位的流。字节流用来读写8位的数据,由于不会对数据作任何转换,因此可以用来处理二进制的数据。在后来的版本中,java.io包中又加入了专门用于字符流处理的类,这是以Reader和Writer为基础派生的一系列的类。另外,为了使对象的状态能够方便地永久保存下来,java.io包中又提供了以字节流为基础的用于对象的永久化保存状态的机制,通过实现Objectlnput和ObjectOutput接口来完成。
ObjectInputStream和ObjectOutputStream是以上两个接口的实现类。
输入数据流
java.io包中所有输入数据流都是从抽象类InputStream继承而来。包括读取数据、标记位置、重置读写指针、获取数据量等
主要数据操作方法
·int read( ):从输入流中读取一个字节的二进制数据。
·int read(byte[ ]b):将多个字节读到数组中,填满整个数组。
·int read(byte[ ] b,int off,int len):从输入流中读取长度为len的数据,从数组b中下标为off的位置开始放置读入的数据,读毕返回读取的字节数。
·void close( ):关闭数据流。当结束对一个数据流的操作时应该将其关闭,同时释放与该数据流相关的资源,因为Java提供系统级的垃圾自动回收功能,所以当一个流对象不再使用时,系统可以自动关闭。但是,为提高程序的安全性和可读性,建议显式关闭输入/输出流。
·int available( ):返回目前可以从数据流中读取的字节数(但实际的读操作所读得的字节数可能大于该返回值)。
·long skip(long l):跳过数据流中指定数量的字节不读取,返回值表示实际跳过的字节数。
输出数据流
java.io包中所有输出数据流大多是从抽象类OutputStream继承而来的
操作方法
·void write(int i):将字节i写入到数据流中,它只输出所读入参数的最低8位。该方法是抽象方法,需要在其输出流子类中加以实现,然后才能使用。
·void write(byte b[ ]):将数组b[ ]中的全部b.length个字节写入数据流。
·void write(byte b[ ],int off,int len):将数组b[]中从下标off开始的len个字节写入数据流。元素b[off]是此操作写入的第一个字节,b[off+len-1]是此操作写入的最后一个字节。以上这些方法用于向输出数据流中写数据。在实际应用中,和操作输入数据流一样,通常以系统允许的最大数据块长度为单位进行写操作。
文件数据流
包括FilelnputStream和FileOutputStream
这两个类用来进行文件的I/O处理,其数据源或数据终点都应当是文件。不支持mark()和reset()方法。
过滤器数据流
一个过滤器数据流在创建时与一个已经存在的数据流相连,这样在从这样的数据流中读取数据时,它提供的是对一个原始输入数据流的内容进行了特定处理的数据。
缓冲区数据流有BufferedlnputStream和BufferedOutputStream,它们是在数据流上增加了一个缓冲区,都属于过滤器数据流。当读写数据时,数据以块为单位先进入缓冲区(块的大小可以进行设置),其后的读写操作则作用于缓冲区。采用这个办法可以降低不同硬件设备之间速度的差异,提高I/O操作的效率。与此同时,这两个流还提供了对mark( )、reset( )和skip( )等方法的支持。
缓冲区数据流创建方式
在创建该类的实例对象时,可以使用两种方法,一种是使用默认缓冲区的大小,例如:
FilelnputStream fis=new FileInputStream(“myFile”);
InputStream is=new BufferedlnputStream(fis);
FileOutputStream fos=new FileOutputStream(“myFile”);
OutputStream os=new BufferedOutputStream(fos);
另一种是自行设置缓冲区的大小,例如:
FilelnputStream fis=new FilelnputStream(“myFile”);
InputStream is=new BufferedlnputStream(fis,1024);
FileOutputStream fos=new FileOutputStream(“myFile”);
OutputStream os=new BufferedOutputStream(fos,1024);
一般在关闭一个缓冲区输出流之前,应先使用flush( )方法,强制输出剩余数据,以确保缓冲区内的所有数据全部写入输出流。
数据数据流
DatalnputStream和DataOutputStream就是这样的两个过滤器数据流,它们允许通过数据流来读写Java基本类型,包括布尔型(boolean)、浮点型(float)等
创建方式
假设is和os分别是前面已经建立好的输入/输出数据流对象,则数据流的创建方式如下。
DatalnputStreamd is=new DatalnputStream(is);
DataOutputStreamd os=new DataOutputStream(os);
三个文件流的区别
在计算机中文件是byte、byte、byte地存储FileInputStream在读取文件的时候,就是一个一个byte地读取,DataInputStream则是在FileInputStream的一个轻量级的包装类,BufferInputStream则是自带缓冲区,默认缓冲区大小为8×1024。
通俗地讲就是:
FileInputStream在读取文件的时候,一滴一滴地把水从一个缸复制到另外一个缸。
DataInputStream则是一瓢一瓢地把水从一个缸复制到另外一个缸。
BufferInputStream则是一桶一桶地把水从一个缸复制到另外一个缸。
对象流
Java中的数据流不仅能对基本数据类型的数据进行操作,而且也提供了把对象写入文件数据流或从文件数据流中读出的功能,这一功能是通过java.io包中的ObjectlnputStream和ObjectOutputStream两个类实现的。能够输入/输出对象的流称为对象流。
序列化
能够记录自己的状态以便将来得到复原的能力,称为对象的持久性(Persistence)。 把对象转换为字节序列的过程称为对象的序列化,把字节序列恢复为对象的过程称为对象的反序列化。
序列化的主要任务是写出对象实例变量的数值。序列化是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。序列化是为了解决在对对象流进行读写操作时所引发的问题。如果变量是另一个对象的引用,则引用的对象也要序列化。这个过程是递归的,保存的结果可以看作是一个对象网。
JDK1.1新增加了接口java.io.Serializable,并对Java虚拟机作了改动以支持将Java对象存为数据流的功能。Serializable接口中没有定义任何方法,只是作为一个标记来指示实现该接口的类可以进行序列化,而没有实现该接口的类的对象则不能长期保存其状态。这意味着只有实现Serializable接口的类才能被序列化。
序列化只能保存对象的非静态成员变量,而不能保存任何成员方法和静态成员变量,并且保存的只是变量的值,对于变量的任何修饰符都不能保存,访问权限(public,protected,private)对于数据域的序列化没有影响,若不希望对象序列化,须加上transient关键字标明。
字符流操作,读者和写者
以Reader和Writer为基础派生的一系列类。
Reader和Writer也是抽象类,只提供了一系列用于字符流处理的接口。它们的方法与InputStream和OutputStream类类似,只不过其中的参数换成了字符或字符数组。Java使用Unicode字符集来表示字符串和字符。
缓冲区读者和缓冲区写者
缓冲流: BufferedReader和BufferedWriter。
除了read( )和write( )方法外,还提供了整行字符的处理方法。
·public String readLine( ):BufferedReader的方法,从输入流中读取一行字符,行结束标志为‘\n’、‘\r’或两者一起。
file类
java.io.File类提供了获得文件基本信息及操作文件的一些方法。
类java*io.File提供了获得文件基本信息及操作文件的一些工具。要创建一个新的File对象可以使用以下3种构造方法。
第1种方法为:
File myFile;
myFile=new File(“mymotd”);
第2种方法为:
myFile=new File(“/”,“mymotd”);
第3种方法为:
File myDir=new File(“/");
myFile=new File(myDir,"mymotd”);
相关方法
与文件名相关的方法
·String getName( ):获取文件名。
·String getPath( ):获取文件路径。
·String getAbsolutePath( ):获取文件绝对路径。
·String getParent( ):获取文件父目录名称。
·boolean renameTo(FilenewName):更改文件名,成功返回true,否则返回false。
文件测定方法
·boolean exists( ):文件对象是否存在。
·boolean canWrite( ):文件对象是否可写。
·boolean canRead( ):文件对象是否可读。
·boolean isFile( ):文件对象是否是文件。
·boolean isDirectory( ):文件对象是否是目录。
·boolean isAbsolute( ):文件对象是否是绝对路径。
常用文件信息和方法
常用文件信息和方法
·long lastModified( ):获取文件最后修改时间。
·long length( ):获取文件长度。
·boolean delete( ):删除文件对象指向的文件,成功则返回true,否则返回false。
随机访问文件
Java语言提供了RandomAccessFile类来处理这种类型的输入/输出。
创建一个随机访问文件有以下两种方法供选择。
1.使用文件名
myRAFile=new RandomAccessFile(String name,String mode);
2.使用文件对象
myRAFile=new RandomAccessFile(File file,String mode);
目录工具
要注意,对于文件名以外的其他属性,在File类中并没有提供对其进行修改的方法。
目录工具
·boolean mkdir( ):创建新目录。
·boolean mkdirs( ):创建多个新目录。
·String[ ]list( ):列出符合模式的文件名。
File类同样可以用来描述一个目录,对其进行的操作也与文件相同,只是不能改变目录名,也不能进行删除,但是可以按模式匹配要求列出目录中所有的文件或子目录。如果目录不存在,可以用mkdir( )和mkdirs( )来生成该目录。两者的区别在于用mkdirs( )可以一次生成多个层次的子目录。
总结
输入流:InputStream或者Reader:从文件中读到程序中;
输出流:OutputStream或者Writer:从程序中输出到文件中;
文件相关的流:FileInputStream、FileOutputStrean、FileReader、FileWriter
缓冲流:BufferedInputStrean、BufferedOutputStream、BufferedReader、BufferedWriter
转换流:InputStreamReader、OutputStreamReader
数据流:DataInputStream、DataOutputStream
对象流:ObjectInputStream、ObjectOutputStream