内容导航
本章节介绍Java中的文件操作。文件操作主要指的是使用Java程序进行输入/输出(I/O)操作,Java中所有的操作类都位于java.io包中,在使用时需要导入此包。在整个Java.io包中最重要的就是五个类和一个接口。其中,五个类指File, OutputStream, InputStream, Writer, Reader,一个接口指的是Serializable,掌握了这些就掌握了I/O操作的核心。
File类
File类是java.io包下代表操作与平台无关的文件和目录的类,也就是说,如果需要在程序中操作文件或目录,就可以通过File类实现对文件或目录的新建,删除,重命名等操作。
操作文件和目录
File类的构造方法定义如下:
public File(String pathName)
其中,pathName指文件路径。因此,在创建File对象的时候必须设置文件路径。列如:操作C盘下的test.txt文件,创建File对象的语句如下。
File file=new File("C:/test.txt");
提示:
- 在Windows操作系统中,文件路径名中的路径分隔符可以使用正斜杠“/”,如"C:/test.txt",也可以使用反斜杠“\”,但必须写成“\\",其中第一个"\"表示转义符,如"C:\\test.txt".
- pathName可以是相对路径也可以是绝对路径。绝对路径是以根目录开头的完整路径。相对路径一般是以项目文件夹为参照物。项目文件下一般有3个文件夹(.idea, out, src),和1个IML文件。
File类的常用方法
方法 | 描述 |
boolean createNewFile() | 创建新文件 |
boolean delete() | 删除文件 |
boolean exists() | 判断文件是否存在 |
boolean isFile() | 判断是否是文件 |
boolean isDirectory() | 判断是否是目录 |
long length() | 返回文件长度,单位为字节;若文件不存在,则返回0L |
String getPath() | 返回文件名对应的路径 |
String getAbsolutePath() | 返回此对象表示的文件的绝对路径 |
提示:如需完成对File类的更多操作,则可随时查阅API帮助文档。对文件操作时有些方法必须使用异常处理。
I/O流概述
File类无法实现对文件内容的操作,也就是无法实现对文件的读写。而Java中的I/O流能够实现数据的输入和输出,是实现文件读写的基础。
提示:如何解释I/O呢?
I即input,指读取操作;O即output,指写入操作。
流,是指一连串流动的字符,是以先进先出的方式发送和接收数据的通道。既然是流,必然是有源端和目的端,它门可以是Internet上的某个统一资源定位符。所谓I/O流就是实现数据输入和输出的流,在I/O流基础上,可以实现对文件的读写操作。Java把所有流类型都封装到java.io包中,用以实现I/O操作。
Java的读取主要以InputStream和Reader作为基类,而写入则主要以OutputStream和Writer作为基类。它门都是一些抽象类,无法直接实例化对象。
按处理单元划分:字节流和字符流
Java中的流可以分为字节流和字符流,他们的区别在于操作的数据单元不同。
- 字节流:以8位字节为操作数据单元的流,可以于操作二进制数据(如操作图片文件)。
- 字符流:以16位的字符为操作数据单元的流,可用于操作文本数据。
通俗地理解,可以把I/O流看做一个水管,这个水管中依次排列着许多水滴,每滴水滴就是一个处理单元,即一个字节或字符。在字节流中每滴水滴是一个字节,在字符流中每滴水滴是一个字符。
字节流
java.io包中的流按存储单元分类主要有字节流和字符流两大类,两类都具有输入/输出操作。它门各自的基类如图所示,这些基类均为抽象类。
字节输出流基类:OutputStream
该类为抽象类,如果需要操作文件,则使用其子类FileOutputStream实例化。
OutputStream类中的主要操作方法
方法 | 描述 |
void close() | 关闭输出流 |
void flush() | 刷新缓冲区 |
void write(byte[] b) | 将每个byte数组写入数据流 |
void write(byte[] b,int off,int len) | 将每个指定范围的byte数组写入数据流 |
void write(int b) | 将一个字节数据写入数据流 |
字节输出流FileOutputStream类
在开发中,通常使用OutputStream类的FileOutputStream子类向文本文件写入数据。
FileOutputStream类常用的构造方法
方法 | 描述 |
FileOutputStream(File file) | 用于创建向指定File对象写数据的文件输出流。file:指定目标文件的对象 |
FileOutputStream(String name) | 用于创建向指定路径的文件写数据的文件输出流。name:指定目标文件的路径字符串 |
FileOutputStream(String name,boolean append) | 创建一个向指定路径的文件写入数据的文件输出流。name:指定目标文件的路径字符串。append:表示是否在文件末尾追加数据,若为true则表示可以在文件末尾追加数据 |
字节输入流基流:InputStream类
InputStream类定义的主要方法
方法 | 描述 |
int read() | 读取一个字节数据 |
int read(byte[] b) | 将数据读取到字节数组中 |
int read(byte[] b,int off,int len) | 从输入流中读取最多len长度的字节,将其保存到字节数组中,保存的位置从off开始 |
void close() | 关闭输入流 |
int available() | 返回输入流读取的字节数 |
字节输入流:FileInputStream类
FileinputStream类的常用构造方法
方法 | 描述 |
FileInputStream(File file) | file:指定目标文件数据源对象 |
FileInputStream(String name) | name:指定目标文件数据源路径字符串 |
注意:
- 按字节读取并显示数据时需要进行强制类型转换。使用read()方法读取数据,每次读取一个8位字节,把它转换为0-255的整数返回,因此,在以单个字节的形式输出数据时,需要进行强制类型转换,将数据类型换为char类型。
- 对是否读取到文件末尾的判断。使用read()方法读取文件中的数据,当返回-1时,即输入流已经读到末尾。
字符流
在Java中,一个字符占用内存的两个字节。如果用字节流处理文本文件,则程序内部需要将字节转换成字符,降低了执行效率,所以当输入和输出文本文件时,尽量使用字符流。Java提供了Writer类和Reader类来操作字符。
字符输出基类:Writer
Writer类是抽象类,它的子类是FileWriter。
Writer类中定义的常用方法
方法 | 描述 |
void write(String str) | 将str字符串中包含的字符输出到输出流中 |
void write(String str,int off,int len) | 将字符串中从off位置开始,长度为len的字符输出到输出流中 |
void close() | 关闭输入流 |
void flush() | 刷新输出流 |
字符输入流基类:Reader
Reader类是字符输入流的基类,它是抽象类,子类是:FileReader
Reader类中的常用方法
方法 | 描述 |
int read() | 从输入流中读取单个字符,放回所读取的字符数据 |
int read(char[] c) | 从输入流中最多读取c.length个字符数据并将其存储在字符数组c中,返回实际读取的字符数 |
int read(char[] c,int off,int len) | 从输入流中最多读取len个字符的数据并将其存储在字符数组c中。在存入数组c中时,并不是从数组起点开始的,而是从off位置开始的,返回实际读取的字符数 |
缓冲流
字符缓冲输出流BufferedWriter类
BufferedWriter类是Writer类的子类,BufferedWriter类可以把一批数据写到缓冲区,默认情况下,只有在缓冲区满的时候,才会把缓冲区的数据真正写到目的地,这样能减少物理写数据的次数,从而提高I/O操作的执行效率。也可以直接刷新缓冲区,方法:对象名.flush();
BufferedWriter类的构造方法:BufferedWriter(Writer out)
字符缓冲输入流BufferedReader类
BuferedReader 类是 Reader 类的子类,它与 FileReader 类的区别在于 BufferedReader 类有缓冲区,它可以先把一批数据读到缓冲区中,接下来的读操作都是从缓冲区内获取数据,避免每次都从数据源读取数据进行字符编码转换,从而提高读取操作的效率。BuferedReader类常用的构造方法如下。
BuferedReader(Reader in)
数据操作流
前面各类流实现了对文本文件的读写操作,但常见的文件读写操作中还有一种二进制文件的读写操作。接下来介绍数据操作流 DataOutputStream和DatalnputStream,使用它们实现对二进制文件的读写操作。
DataOutputStream类和 DatalnputStream类
DataOutputStream 类可以按照与平台无关的方式向流中写入基本数据类型的数据,如int,float.long、double 和boolean等。此外,DataOutputStream类的 writeUTFO方法能写入采用UTF-8 字符编
码的字符串。
序列化与反序列化
序列化就是将对象的状态更轻松简单地存储到特定的存储介质中的过程,也就是将对象状态转换为可保持或可传输格式的过程。使用序列化的意义在于将Java对象序列化后,可以将其转换为字节序列,这些字节序列可以被保存在磁盘上,也可以借助网络进行传输,同时序列化后的对象保存的是二进制状态,这样实现了平台无关性,即可以将在Windows操作系统中实现序列化一个对象,传输到Linux操作系统的机器上。反序列化是将特定的存储介质中的数据重新构造对象的过程,通过反序列化后得到相同对象,而无需担心数据因平台不同出现异常。
实现序列化和反序列化操作,需要使用对象操作流,以下分别介绍对象输出流(ObjectInputStream)和对象输入流(ObjectOutputStream)。
对象输出流ObjectOutputStream实现序列化
对象的序列化,是把一个对象变为二进制的数据流的一种方法,通过对象序列化可以方便地实现对象的传输和存储。如果一个类的对象需要被序列化,则这个对象所属类必须实现java.io.Serializable 接口,最好不要重写toString()方法。
ObjectOutputStream类的常用方法
方法名 | 描述 | 类型 |
ObjectOutputStream(OutputStream out) | 创建输出流对象 | 构造方法 |
final void writeObject(Object obj) | 将指定对象写入流。从位置0开始,会覆盖文件原有信息 | 实例方法 |
对象输入流ObjectInputStream实现反序列化
ObjectInputStream类的常用方法
方法 | 描述 | 类型 |
ObjectInputStream(InputStream in) | 创建输入流对象 | 构造方法 |
final Object readObject() | 从指定位置读取对象 | 实例方法 |
在反序列化时,readObject()方法返回的是Object对象,因此,如果需要转换为XXX对象,则需要进行强制类型转换。
注意:如果使用序列化方式向文件中写入多个对象,那么反序列化恢复对象时,也按照写入的顺序读取。
到此为止,介绍了Java体系种主要的I/O流,当然,除此之外,还有其他流,这些流看上去杂乱,但实际上是很有规律的。
Java体系中常用流的分类
分类 | 字节输出流 | 字节输入流 | 字符输出流 | 字符输入流 |
基类 | OutputStream | InputStream | Writer | Reader |
文件流 | FileOutputStream | FileInputStream | FileWriter | FileReader |
缓冲流 | BufferedOutputStream | BufferedInputStream | BufferedWriter | BufferedReader |
对象流 | ObjectOutputStream | ObjectInputStream | —— | —— |
数据操作流 | DataOutputStream | DatalnputStream | —— | —— |
本章总结
- File类用来访问文件和目录。
- 流,是指一连串流动的字符,是以先进先出的方式发送和接收数据的通道。Java中的I/O流正是实现文件读写的基础,它可以方便地实现数据的输入和输出。
- 流具有明确的方向性,按照流的流向来分,其可以分为输入流和输出流。
- 按照处理单元划分,java中的流可以分为字节流和字符流。
- 按照流的角色划分,Java中的流可以为节点流和处理流。
- FileInputStream和FileOutputStream实现以字节流的方式读写文本文件。
- FileWriter类和FileReader类实现以字符流的方式读写文本文件。
- BufferedWriter和BufferedReader类为字符缓冲流,具有缓冲区,执行效率更高。
- 序列化就是将对象的状态存储到特定的存储介质中的过程,也就是将对象状态转换为可保持或可传输格式的过程。反序列化是将存储介质中的数据重新构造为对象的过程。
- 序列化和反序列化需使用对象输入/输出流流ObjectInputStream和ObjectOutputStream。
努力造就实力,态度决定高度。