在编程中,数据是存储在内存中的,但为了长久保存数据,就要使用文件(File)的形式存储,将数据存储在 I/O 设备上。 File类的对象代表操作系统的文件,File 类在 java.io.File 包下。File类提供了诸如:创建文件对象代表文件,获取文件信息、删除文件、创建文件等功能。
public File(String pathname) // 根据文件路径创建文件对象
public File(String parent, String chile) // 根据父目录 + 孩子文件路径,创建一个新的 File 实例,父目录用路径表示
public File(File parent, String child) // 根据文件路径创建一个新的 File 实例,路径可以是绝对路径或者相对路径
ps:File 类的对象仅仅是一个路径名,这个路径可以是存在的,也可以是不存在的。
绝对路径:由于文件管理是树形结构,从树的根节点开始一直到达所需的节点的路径所描述的方式就是绝对路径。
File file1 = new File("D:\\wenjian\\a.txt");相对路径:除了可以从根节点开始进行路径的描述,也可以从任意节点出发进行路径描述,这种描述方式就被称为相对路径。
File file2 = new File("..\\a.txt");
| 方法 | 说明 |
|---|---|
| String getParent() | 返回 File 对象的父目录文件路径 |
| String getName() | 返回 FIle 对象的纯文件名称 |
| String getPath() | 返回 File 对象的文件路径 |
| String getAbsolutePath() | 返回 File 对象的绝对路径 |
| boolean exists() | 判断 File 对象描述的文件是否真实存在 |
| boolean isDirectory() | 判断 File 对象代表的文件是否是一个目录 |
| boolean isFile() | 判断 File 对象代表的文件是否是一个普通文件 |
| boolean createNewFile() | 根据 File 对象,自动创建一个空文件。成功创建后返回 true |
| boolean delete() | 根据 File 对象,删除该文件。成功删除后返回 true |
| boolean mkdir() | 创建 File 对象代表的目录 |
| boolean mkdirs() | 创建 File 对象代表的目录,如果必要,会创建中间目录 |
| String[] list() | 返回 File 对象代表的目录下的所有文件名 |
| File[] listFiles() | 返回 File 对象代表的目录下的所有文件,以 File 对象表示 |
代码示例:
/**
* 普通文件的创建、删除
*/
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
File file = new File("hello-world.txt"); // 要求该文件不存在,才能看到相同
的现象
System.out.println(file.exists());
System.out.println(file.isDirectory());
System.out.println(file.isFile());
System.out.println(file.createNewFile());
System.out.println(file.exists());
System.out.println(file.isDirectory());
System.out.println(file.isFile());
System.out.println(file.createNewFile());
}
}
/**
* 普通文件的删除
*/
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
File file = new File("some-file.txt"); // 要求该文件不存在,才能看到相同的现
象
System.out.println(file.exists());
System.out.println(file.createNewFile());
System.out.println(file.exists());
System.out.println(file.delete());
System.out.println(file.exists());
}
}
/**
* 目录的创建
*/
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
File dir = new File("some-dir"); // 要求该目录不存在,才能看到相同的现象
System.out.println(dir.isDirectory());
System.out.println(dir.isFile());
System.out.println(dir.mkdir());
System.out.println(dir.isDirectory());
System.out.println(dir.isFile());
}
}

I 表示 intput,把硬盘文件中的数据读入到内存的过程称之输入,负责读。
O 表示 output,把内存中的数据写出到硬盘文件的过程,称之输出,负责写。
以内存为基准,来自磁盘文件/网络中的数据以字节的形式读入到内存中去的流称为字节输入流。
| 方法 | 说明 |
|---|---|
| int read() | 读取一个字节的数据,返回 -1 代表已经完全读完了 |
| int read(byte[] b) | 最多读取 b.length 字节的数据到 b 中,返回实际读到的数量;-1 代表以及读完了 |
| int read(byte[] b,int off, int len) | 最多读取 len - off 字节的数据到 b 中,放在从 off 开始,返回实际读到数量;-1 代表以及读完了 |
| void close() | 关闭字节流 |
InputStream 只是一个抽象类,要使用还需要具体的实现类。关于 InputStream
的实现类有很多,基本可以认为不同的输入设备都可以对应一个 InputStream 类,我们现在只关心从文件中读取,所以使用
FileInputStream.
FileInputStream(读取文件的字节)
| 方法 | 说明 |
|---|---|
| FileInputStream(File file) | 利用 File 构造文件输入流 |
| FileInputStream(String name) | 利用文件路径构造文件输入流 |
如何读取文件的全部字节:
自己定义一个字节数组与文件的大小一样大,然后使用读取字节数组的方法,一次性读取完成。
read 有两种方法,一种是每次读取一个字节,另一种就是每次读取一个字节数组。
两种方法代码示例:
import java.io.*;
// 需要先在项目目录下准备好一个 hello.txt 的文件,里面填充 "Hello" 的内容
public class Main {
public static void main(String[] args) throws IOException {
try (InputStream is = new FileInputStream("hello.txt")) {
while (true) {
int b = is.read();
if (b == -1) {
// 代表文件已经全部读完
break;
}
System.out.printf("%c", b);
}
}
}
}
public class Main2 {
public static void main(String[] args) throws IOException {
try (InputStream is = new FileInputStream("hello.txt")) {
byte[] buf = new byte[1024];
int len;
while (true) {
len = is.read(buf);
if (len == -1) {
// 代表文件已经全部读完
break;
}
for (int i = 0; i < len; i++) {
System.out.printf("%c", buf[i]);
}
}
}
}
}
import java.io.*;
两种 read 的方式,相比较而言,第二中的 IO 次数更少,性能更好。
按字节进行数据读:
try (InputStream is = ...) {
byte[] buf = new byte[1024];
while (true) {
int n = is.read(buf);
if (n == -1) {
break;
}
// buf 的 [0, n) 表示读到的数据,按业务进行处理
}
}
以内存为基准,把内存中的数据以字节写出到磁盘文件或者网络中去的流称为字节输出流。
| 方法 | 说明 |
|---|---|
| void write(int b) | 写入要给字节的数据 |
| void write(byte[] b) | 将 b 这个字符数组中的数据全部写入 os 中 |
| int write(byte[] b, int off, int len) | 将 b 这个字符数组中从 off 开始的数据写入 os 中,一共写 len 个 |
| void close() | 关闭字节流 |
| void flush() | 我们知道 I/O 的速度是很慢的,所以,大多的 OutputStream 为了减少设备操作的次数,在写数据的时候都会将数据先暂时写入内存的一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写入设备中,这个区域一般称为缓冲区。但造成一个结果,就是我们写的数据,很可能会遗留一部分在缓冲区中。需要在最后或者合适的位置,调用 flush(刷新)操作,将数据刷到设备中。 |
OutputStream 同样只是一个抽象类,要使用还需要具体的实现类。我们现在还是只关心写入文件中,所以使用 FileOutputStream。
按字节进行数据写:
try (OutputStream os = ...) {
byte[] buf = new byte[1024];
while (/* 还有未完成的业务数据 */) {
// 将业务数据填入 buf 中,长度为 n
int n = ...;
os.write(buf, 0, n);
}
os.flush(); // 进行数据刷新操作
}
以内存为基准,来自磁盘文件/网络中的数据以字符的形式读入到内存中去的流称为字符输入流。
对于字符类型不能直接使用 InputStream 进行读取,要利用 Scanner 进行字符读取:
Scanner(InputStream is, String charset) // 使用 charset 字符集进行 is 的扫描读取
代码示例:
import java.io.*;
import java.util.*;
// 需要先在项目目录下准备好一个 hello.txt 的文件,里面填充 "你好中国" 的内容
public class Main {
public static void main(String[] args) throws IOException {
try (InputStream is = new FileInputStream("hello.txt")) {
try (Scanner scanner = new Scanner(is, "UTF-8")) {
while (scanner.hasNext()) {
String s = scanner.next();
System.out.print(s);
}
}
}
}
}
按字符进行数据读:
try (InputStream is = ...) {
try (Scanner scanner = new Scanner(is, "UTF-8")) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
}
}
}
以内存为基准,把内存中的数据以字符写到磁盘/网络介质中去的流称为字符输出流。
对于字符进行数据写,OutputStream 不太方便,所以将 OutputStream 处理下,使用 PrintWriter 类来完成输出,因为 PrintWriter 类中提供了我们熟悉的 print/println/printf 方法。
代码示例:
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
try (OutputStream os = new FileOutputStream("output.txt")) {
try (OutputStreamWriter osWriter = new OutputStreamWriter(os, "UTF-
8")) {
try (PrintWriter writer = new PrintWriter(osWriter)) {
writer.println("我是第一行");
writer.print("我的第二行\r\n");
writer.printf("%d: 我的第三行\r\n", 1 + 1);
writer.flush();
}
}
}
}
}
按字符进行数据写:
try (OutputStream os = ...) {
try (OutputStreamWriter osWriter = new OutputStreamWriter(os, "UTF-8")) {
try (PrintWriter writer = new PrintWriter(osWriter)) {
while (/* 还有未完成的业务数据 */) {
writer.println(...);
}
writer.flush(); // 进行数据刷新操作
}
}
}
活动地址:CSDN21天学习挑战赛