目录
- 一、File类
- 1、操作文件和目录
- 二、I/O流概述
- 1、按流向划分:输入流和输出流
- 2、按处理单元划分:字节流和字符流
- 3、按流的角色划分:节点流和处理流
- 三、字节流
- 1、字节输出流基类:OutputStream
- 2、字节输出流FileOutputStream类
- 3、字节输入流基类:InputStream
- 4、字节输入流FileInputStream类
- 四、字符流
- 1、字符输出流基类:Writer
- 2、字符输出流FileWrite类
- 3、字符输入流基类:Reader
- 4、字符输入流FileReader
一、File类
在程勋运行的过程中,输入/输出是常用的操作,也是必需的部分。允许程序读取外部数据,包括来自磁盘、光盘、文件等存储设备的数据,这类操作属于输入数据;同时允许程序记录运行状态,将程序数据输出到磁盘、光盘、文件等存储设备中,这类操作属于输出数据,数据的输入和输出离不开文件,经常使用到的文件类型很多,如扩展名为 .txt、.doc、.class的文件等。
File类是java.io包下代表操作与平台无关的文件和目录的类,也就是说,如果需要在程序中操作文件或目录,就可以通过File类实现对文件或目录的新建、删除、重命名等操作。
1、操作文件和目录
在程序中,一个File对象可以代表一个文件或目录。它可以查出与文件相关的信息,如名称、修改日期、文件大小等。File类的构造方法定义如下:
public File(String pathName)
其中,pathName指定文件路径。因此,在创建File对象的时候必须设置文件路径。
例如:
File file=new File("C://test.txt");
注意:在Windows操作系统中,文件路径名中的路径分隔符可以使用正斜杠“ / ”,如“C:/test.txt”,也可以使用反斜杠“ \ ”,但必须写成“ \ ”,其中第一个“ \ ”表示转义符。
方法 | 描述 |
---|---|
boolean createNewFile() | 创建新文件 |
boolean delete() | 删除文件 |
boolean exists() | 判断文件是否存在 |
Boolean isFile() | 判断是否是文件 |
boolean isDirectory() | 判断是否是目录 |
long length() | 返回文件长度,单位为字节;若文件不存在,则返回0L |
String getPath() | 返回文件名对应的相对路径 |
String getAbsolutePath() | 返回此对象文件的绝对路径 |
String getName() | 返回此对象表示的文件或目录的名称 |
在这只列举了File类的一些常用方法,在实际开发中,如需完成对File类的更多操作,则可随时查询API帮助文档。
在程序当前目录下创建非空文件test.txt,编码实现创建文件对象,判断文件是否存在,输出路径、文件名、长度及判断File对象存储内存是否为文件。
示例:
import java.io.File;
public class FileTest {
public static void main(String[] args) {
File file=new File("text.txt");
if (file.exists()){
if (file.isFile()){
System.out.println("文件名:"+file.getName()+",文件长度:"+file.length()+"字节");
System.out.println("文件路径是:"+file.getPath());
System.out.println("文件绝对路径是:"+file.getAbsolutePath());
}
if (file.isDirectory()){
System.out.println("此文件是目录");
}
}else {
System.out.println("此文件不存在!");
}
}
}
文件名:test.txt,文件长度:32字节。
文件路径是:test.txt
文件绝对路径是:D:\IdeaProjects\Exam\test.txt
其他方法类似,就不在这坐多解释和实例了!
二、I/O流概述
File类能够实现对文件和目录的创建、删除等基础性操作,但是无法实现对文件内容的操作,也就是无法实现对文件的读写。而在Java中的I/O流能够方便地实现数据的输入和输出,是实现文件读写的基础。
流,是指一连串流动的字符,是以先进先出的方式发送和接收数据的通道。既然是流,必须是源端和目的端,它们可以是计算机内存的某些区域,也可以是磁盘、文件等,甚至可以是Internet上的某个统一资源定位符。所谓I/O流就是实现数据输入和输出的流,在I/O流的基础上,可以实现对文件的读写操作。
注意:
I/O流的 I 即 input,指读入操作;O 即 output,指写出操作。
1、按流向划分:输入流和输出流
流具有明确的方向性,按照流的流向来分,可以分为输入流和输出流。
- 输入流:只能从中读取数据,而不能写入数据的流,实现程序从数据源中读数据。
- 输出流:只能向其写入数据,而不能从中读取数据的流,实现程序向目标数据中写数据。
注意:
按照流的流向进行分类时,输入流完成数据读入操作,输出流完成数据写出操作,这里的“出”和“入”一定是从程序运行所在内存的角度来论述。如果从文件或磁盘的角度来论述,方向恰恰相反,混淆了概念就会引发错误。
2、按处理单元划分:字节流和字符流
按照处理单元划分,Java中的流可分为字节流和字符流,它们的区别在于操作的数据单元不同。
- 字节流:以8位字节为操作数据单元的流,可用于操作二进制数据(如操作图片文件)。
- 字符流:以16位的字符为操作数据单元的流,可用于操作文本数据。
通俗地理解,可以把I/O流看作一个水管,这个水管中依次排列着许多水滴,每滴水滴就是一个处理单元,即一个字节或字符。
3、按流的角色划分:节点流和处理流
按照流的角色划分,Java中的流可分为节点流和处理流。
- 节点流:可以直接向一个特定的存储介质(如磁盘、文件)读写数据的流。
- 处理流:用于对一个已存在的流进行连接和封装,是通过封装后的流实现数据读写操作的流。
三、字节流
java.io包中的流按存储单元分类主要有字节流和字符流量大类,两类都具有输入/输出操作。
1、字节输出流基类:OutputStream
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) | 将一个字节数据写入数据流 |
2、字节输出流FileOutputStream类
在实际应用中,通常使用OutputStream类的FileOutputStream子类向文本写入数据,常用的构造方法如下表格:
方法 | 描述 |
---|---|
FileOutputSteam(File file) | 用于创建向指定File对象写数据的文件输出流。file:指定目标文件的对象 |
FileOutputSteam(String name) | 用于创建向指定路径的文件写数据的文件输出流。name:指定目标文件的路径字符串 |
FileOutputSteam(String name,boolean append) | 创建一个向指定路径的文件写入数据的文件输出流。name:指定目标文件的路径字符串。append:表示是否在文件末尾追加数据,若为true则表示可以在文件末尾 |
注意: 在以上表格中,前两种构造方法在向文件写数据时将覆盖文件中原有的内容。
另外,在使用FileOutputStream类的构造方法创建对象时,如果相应的文件不存在,就会自动新建一个文件。如果参数file或name表示的文件路径是一个目录,则会抛出FileNotFoundexception异常。
下面通过示例介绍使用字节输出流向文本文件写入数据,实现向D:/doc/test.txt文件中写入字符串"I love java!"。
代码示例:
public class OutputstreamTest {
public static void main(String[] args) {
OutputStream fos = null;
try {
//2.创建文件输出流对象
fos = new FileOutputStream("D:\\doc\\test.txt", true);
//3.执行写操作
String str = "I Love You";//准备一个字符串
byte[] words = str.getBytes();//将字符串转换为byte数组
fos.write(words, 0, words.length);
System.out.println("文件已写入成功!");
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
//4.关闭输出流
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
执行以上代码后,打开D:/doc/test.txt,查看运行结果,重复执行,可实现向文件末尾继续追加数据。
注意:
在编写代码时会发现,以上程序在创建输出流对象、执行写操作、关闭输出流时都可以会有IOException异常发生,因此除FileNotFoundException异常外,还需处理IOException异常。
3、字节输入流基类:InputStream
既然可以使用OutputStream类向文件中写数据,那么也可以通过InputStream类从文件中读数据。
InputStream类同样也是抽象类,该类中定义的主要方法如以下表格:
方法 | 描述 |
---|---|
int read() | 读取一个字节数据 |
int read(byte[] b) | 将数据读取到字节数组中 |
int read(byte[] b,in off,int len) | 从输入流中读取最多len的长度的字节,将其保存到字节数组中,保存的位置从off开始 |
void close() | 关闭输入流 |
int available() | 返回输入流读取的字节数 |
4、字节输入流FileInputStream类
在实际开发中,通常使用InputStream类的FileInputStream子类实现文本内容的读取,其常用构造方法如以下表:
方法 | 描述 |
---|---|
FileInputStream(File file) | 用于创建从指定File对象读取数据的文件输入流。file:指定目录文件数据源对象 |
FileInputStream(String name) | 用于创建从指定路径的文件读取数据的文件输入流。name:指定目标文件数据源路径字符串 |
下面通过示例介绍使用字节输入流从指定文件读取数据。
代码示例:
public class InputStreamTest {
public static void main(String[] args) {
InputStream fis = null;
try {
//2.创建文件输入流对象
fis = new FileInputStream("D:\\test.txt");
System.out.println("可读取的字节数:" + fis.available());
//3.执行读操作
byte[] words=new byte[1024];//创建字节数组
int len=0;//实际读取长度
int data = 0;
//循环读取数据
System.out.println("文件的内容:");
while ((data = fis.read()) != -1) {
System.out.print((char) data + "");}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
//4.关闭输出流
try{
if (fis!=null){
fis.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
}
运行结果
四、字符流
在Java中,一个字符占用内存的两个字节。如果用字节流处理文本文件,则程序内部需要将字节转换成字符,降低了执行效率,所以当输入和输出文本文件时,尽量使用字符流。Java提供了Writer类和Reader类来操作字符。
1、字符输出流基类:Writer
Writer类是字符输出流的抽象基类,Writer类中定义的常用方法如以下表格:
方法 | 描述 |
---|---|
void write(String str) | 将str字符串中包含的字符输出到输出流中 |
void write(String str,int off,int len) | 将字符串中从off位置开始、长度为len的字符输出到输出流中 |
void close() | 关闭输出流 |
void flush() | 刷新输出流 |
2、字符输出流FileWrite类
FileWriter类是Writer类常用的子类,使用该类可以以字符为数据处理单元向文本中写数据。
下面通过示例完成使用FileWriter类向文本文件中写数据。
代码示例:
public class FileWriterTest {
public static void main(String[] args) {
Writer fw=null;
try {
//创建FileWriter对象
fw=new FileWriter("D:/doc/mysaying.txt");
OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("D:/doc/mysaying.txt"),"UTF-8");
//向文件写数据
fw.write("预测未来的最好方式就是创造未来!");
fw.flush();//刷新缓冲区
System.out.println("文件写入成功!");
} catch (IOException e) {
e.printStackTrace();
System.out.println("文件不存在!");
} finally {
if (fw!=null){
try {
fw.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
运行结果:
3、字符输入流基类:Reader
Reader类是字符输入流的基类,它是抽象,Reader类中的常用方法如以下表格:
方法 | 描述 |
---|---|
int read() | 从输入流中读取单个字符,返回所读取的字符数据 |
int read(char[] c) | 从输入流中最多读取c.length个字符数据并将其存储在字符数组c中,返回实际读取的字符数 |
int read(char[] c,int off,int len) | 从输入流中最多读取len个字符的数据并将其存储在字符数组c中。在存入数组c中,并不是从数组起点开始的,而是从off位置开始的,返回实际读取的字符数 |
对比Reader类和InputStream类所提供的方法,会发现它们基本是相同的。如果将输入流比作水管,那么可以通过read()方法每次读取一滴“水滴”,也可以通过read(byte[] c)方法或read(char[] c,int off,int len)方法每次读取多滴“水滴”,多次重复执行取水的过程,当以上方法返回值为-1时,表示到了输入流的结束点,也就是取水完毕。
4、字符输入流FileReader
Reader类同样是抽象类,可以使用其子类FileReader创建对象。
代码示例:
public class FileReaderTest {
public static void main(String[] args) {
Reader fr = null;
try {
//2.实例化FileReader对象
fr = new FileReader("D:/doc/诗词.txt");
char[] ch = new char[1024];//创建字符数组作为转储容器
int len = 0;//保存实际存储的字符数
//3.循环读取数据
while ((len = fr.read(ch)) > 0) {
System.out.println(new String(ch,0,len));
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
//4.关闭流
if (fr != null) {
try {
fr.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
运行结果: