文章目录
- 1.File类
- 2.流的概念
- 3.InputStream
- 4.OutputStream
- 5.Reader
- 6.Writer
- 7.使用Scanner读文件
- 8.使用PrintWriter写文件
- 9.close()方法
- 10.flush()方法
- 10.总结
1.File类
File类是Java中用于表示文件或目录的类。它提供了一些方法来操作文件和目录的属性和内容,可以进行文件的创建、删除、重命名等操作。
File类可以用于表示磁盘上的实际文件或目录,也可以表示一个虚拟的文件或目录。File对象可以通过路径来创建,路径可以是绝对路径或相对路径。
-
绝对路径(Absolute Path):绝对路径是从文件系统的根目录开始描述文件或目录的位置。它包含了完整的路径信息,从根目录一直到目标文件或目录的全路径。在Windows中,绝对路径以盘符(例如C:\)开头;在Unix/Linux系统中,绝对路径以斜杠(/)开头。
-
相对路径(Relative Path):相对路径是相对于当前工作目录或引用文件所在位置的路径。它指定文件或目录相对于当前位置的位置关系。相对路径没有从根目录开始的完整路径,而是通过使用“.”(当前目录)和“…”(上级目录)等符号来描述位置关系。
创建File类对象:
File file = new File("文件路径(绝对/相对)");
// 此处的文件路径不要要求一定存在
File类中的常用方法:
方法 | 描述 |
---|---|
getParent() | 获取文件的父目录 |
getName() | 获取文件的名字 |
getPath() | 获取文件的路径 |
getAbsolutePath() | 获取绝对路径 |
getCanonicalPath() | 获取标准的绝地路径。 |
createNewFile() | 创建文件 |
exists() | 判断文件是否存在 |
delete() | 删除文件 |
mkdir() | 创建目录(与src同一级) |
mkdirs() | 创建多级目录 |
isDirectory() | 判断是否为目录 |
isFile() | 是否为文件 |
renameTo(File dest) | 重命名 |
list() | 返回当前目录下所有文件名 |
上述都是一些获取文件和目录的信息以及增删等操作. 接下来介绍一些文件的读写操作.
2.流的概念
在Java的IO操作中,流(Stream)是指数据的传输管道。它将程序与输入/输出设备(例如文件、网络连接等)连接起来,使得数据能够在程序和设备之间流动。
Java的IO流分为输入流和输出流两种类型。
- 输入流用于从外部读取数据
- 输出流用于向外部写入数据。
Java中的流操作按照字节或字符的方式进行。字节流(byte stream)是以字节为单位进行数据传输的,适用于处理二进制数据。字符流(character stream)是以字符为单位进行数据传输的,适用于处理文本数据。
这里的InputStream,OutputStream,Reader和Writer都是抽象类
.Java提供了一些实现这些抽象父类的子类,用于应对不同的场景.
3.InputStream
InputStream的子类可以根据不同的数据源提供不同的实现,例如FileInputStream用于从文件中读取数据,ByteArrayInputStream用于从字节数组中读取数据,SocketInputStream用于从网络连接中读取数据等。
对于InputStream,主要讲解FileInputStream
public static void main(String[] args) throws FileNotFoundException {
InputStream inputStream = new FileInputStream("文件路径");
inputStream.close();
}
在创建实例时,要传入一个文件路径.这里需要处理一个异常FileNotFoundException
(文件没找到).
读文件需要先打开文件,打开才能读,读完之后要关闭文件(close)
InputStream类的常用方法为read()和close()
方法
close()方法:关闭输入流,释放与之关联的资源。
而read()方法有三个版本:
- int read():从输入流中读取数据的下一个字节,并返回读取到的字节值。如果已经到达流的末尾,则返回-1。
- int read(byte[] b):从输入流中最多读取b.length个字节,并将其存储在字节数组b中。返回实际读取的字节数量。如果已经到达流的末尾,则返回-1。
- int read(byte b[], int off, int len): 从输入流中读取最多len个字节,并将其存储在从偏移量off开始的字节数组b中。
4.OutputStream
OutputStream的子类可以根据不同的目的地提供不同的实现,例如FileOutputStream用于向文件中写入数据,ByteArrayOutputStream用于向字节数组中写入数据,SocketOutputStream用于向网络连接中写入数据等。
对于OutputStream,主要讲解FileOutputStream
public static void main(String[] args) throws IOException {
OutputStream outputStream = new FileOutputStream("文件路径");
outputStream.close();
}
close()方法: 关闭输出流,释放资源.
OutputStream中的一个常用方法: write()
:
这里有三个重载的版本
- write(int b):写入一个字节到输出流中。b是一个整数,表示要写入的字节的值(范围是0~255)。
- write(byte[] b):将整个字节数组b写入输出流中。
- write(byte[] b, int off, int len):将字节数组b中从偏移量off开始的len个字节写入输出流中。
注意:使用OutputStream写文件时,只要文件打开成功,就会把文件原有的内容清空.
5.Reader
Reader的子类可以根据不同的字符输入源提供不同的实现,例如FileReader用于从文件中读取字符数据,StringReader用于从字符串中读取字符数据,BufferedReader用于从字符缓冲区中读取字符数据等。
使用方式于InputStream类似,只不过Reader是以字符流的形式进行读文件
public static void main(String[] args) throws IOException {
Reader reader = new FileReader("");
reader.close();
}
- read():读取单个字符,并返回其Unicode值。如果已到达流的末尾,则返回-1。
- read(char[] cbuf):将字符读入到指定的字符数组cbuf中,并返回读取的字符数。
- read(char[] cbuf, int off, int len):将字符读入到指定的字符数组cbuf中,从偏移量off开始,最多读取len个字符,并返回实际读取的字符数。
- read(CharBuffer target):将字符读入到指定的CharBuffer对象中,并返回读取的字符数。
6.Writer
Writer是用于向字符输出流中写入字符数据。
Writer的子类可以根据不同的字符输出目的地提供不同的实现,例如FileWriter用于向文件中写入字符数据,StringWriter用于向字符串中写入字符数据,BufferedWriter用于向字符缓冲区中写入字符数据等。
- write(int c):将指定的字符写入输出流中。
- write(String str):将字符串写入输出流中。
- write(char[] cbuf):将字符数组中的字符写入输出流中。
- write(String str, int off, int len):将字符串中从偏移量off开始的len个字符写入输出流中。
- write(char[] cbuf, int off, int len):将字符数组中从偏移量off开始的len个字符写入输出流中。
7.使用Scanner读文件
追对于文本文件,也可以使用Scanner进行读取
例如这里有一个test.txt文件
接下来介绍使用Scanner进行读文件
public class Demo5 {
public static void main(String[] args) throws IOException {
InputStream inputStream = new FileInputStream("test.txt");
Scanner scanner = new Scanner(inputStream);
while (scanner.hasNext()){
System.out.println(scanner.next());
}
inputStream.close();
}
}
运行结果:
解释一下:InputStream是字节流,Scanner是在InputStream的基础上,包装出来的字符流.
8.使用PrintWriter写文件
与Scanner进行读文件类似,通过将FileOutputStream对象作为参数,创建了一个PrintWriter对象printWriter。
PrintWriter类提供了一系列的print和println方法,用于以友好的方式输出数据。这些方法可以接受不同类型的数据作为参数,并将其转换为字符串并写入输出流中。
例如,常用的方法包括:
- print(boolean b) / println(boolean b):以字符串形式写入一个boolean值。
- print(char c) / println(char c):以字符串形式写入一个字符。
- print(int i) / println(int i):以字符串形式写入一个整数。
- print(double d) / println(double d):以字符串形式写入一个双精度浮点数。
- print(String s) / println(String s):写入一个字符串。
- printf(String format, Object… args):使用指定的格式字符串和参数进行格式化输出。
需要注意的是,在使用完PrintWriter后,需要调用close()
方法关闭流,以确保数据被正确地写入目的地并释放资源。
代码:
public class Demo6 {
public static void main(String[] args) throws IOException {
OutputStream outputStream = new FileOutputStream("test.txt");
PrintWriter printWriter = new PrintWriter(outputStream);
printWriter.printf("hello PrintWriter");
printWriter.close();
outputStream.close();
}
}
运行结果:
9.close()方法
上述输入流和输出流的读文件和写文件后,都要进行close.是为什么呢?
原因是 每个进程都对应者PCB(可能是多个),PCB里有一个字段,文件描述符表(同一个进程里有多个PCB共同使用同一份文件描述符表),进程没打开一个文件,就会在文件描述表中创建一个项表示 一个文件.关闭文件意味着释放文件描述表中的项.如果不关闭文件,表项就在这里占着位置. 如果持续打开文件,不关闭,文件描述符表中的项就会被耗尽,从而导致后续打开文件失败. 这也称
"文件资源泄漏"
为了避免上述问题,就需要保证close方法一定能被执行到.
因此就可以使用 try,finally保证close方法一定被执行到
public static void main(String[] args) throws IOException {
Writer writer = null;
try {
writer = new FileWriter("文件路径");
// do something
} finally {
writer.close();
}
}
除了上述这种写法,还有一种写法(try with resources
)
public static void main(String[] args) throws IOException {
try(Writer writer = new FileWriter("文件路径")) {
// do something
}
}
当try中的代码执行结束,就会自动调用对应对象的close方法.而且()中可以放多个对象,对象之间用;
进行分割
10.flush()方法
flush()方法是Java IO流中的一个方法,用于刷新缓冲区,并确保数据被写入到目的地。
缓冲区(Buffer)是用于临时存储数据的一块内存区域,它可以提高IO操作的效率。
在Java的IO流中,使用缓冲区可以减少单次IO操作的次数,从而提高读取和写入数据的效率。通常情况下,IO流会使用内部的缓冲区来存储数据,然后在一定条件下将缓冲区中的数据进行读取或写入。
在Java的输出流(OutputStream/Writer)中,flush()方法的作用是将缓冲区中的数据强制刷新到目的地。通常情况下,输出流会使用内部的缓冲区来提高写入效率,即将数据先写入到缓冲区中,然后再一次性写入到目的地。而flush()方法的调用可以让输出流立即将缓冲区的数据写入到目的地,而不是等到缓冲区满或流关闭时才写入。
注: 调用close()方法也会刷新缓冲区,并确保所有数据都被写入
10.总结
Java IO流主要涉及以下类:
- InputStream和OutputStream:字节流的基类,用于读取和写入字节数据。
- Reader和Writer:字符流的基类,用于读取和写入字符数据。
- FileInputStream和FileOutputStream:用于从文件中读取和写入字节数据。
- FileReader和FileWriter:用于从文件中读取和写入字符数据。
同时可以使用Scanner和PrintWriter简化开发,使用完流对象后,一定要记得调用close操作.