Java I/O框架
File 类
代表物理盘符中的一个文件或文件夹。
常用方法
| ⽅法名 | 描述 |
|---|---|
| createNewFile() | 创建⼀个新⽂件。 |
| mkdir() | 创建⼀个新⽬录。 |
| delete() | 删除⽂件或空⽬录。 |
| exists() | 判断File对象所对象所代表的对象是否存在。 |
| getAbsolutePath() | 获取⽂件的绝对路径。 |
| getName() | 取得名字。 |
| getParent() | 获取⽂件/⽬录所在的⽬录。 |
| isDirectory() | 是否是⽬录。 |
| isFile() | 是否是⽂件。 |
| length() | 获得⽂件的⻓度。 |
| listFiles() | 列出⽬录中的所有内容。 |
| renameTo() | 修改⽂件名为。 |
FileFilter 接口
FileFilter 文件过滤接口
- boolean accept(File pathname)
- 当调用File类中的
listFiles()方法时,支持传⼊FileFilter接⼝接⼝实现类,对获取⽂件进⾏过滤,只有 > 满⾜条件的⽂件的才可出现在listFiles()的返回值中。
public static void directoryOperator() throws Exception {
File file = new File("D:\ccc\aaa");
if (!file.exists()) {
boolean isCreateFile = file.mkdirs();
System.out.println(isCreateFile);
} else {
System.out.println(file.getName() + "已存在");
}
// 删除
// System.out.println(file.delete());
// file.deleteOnExit();
// 获取
System.out.println("获取路径" + file.getPath());
System.out.println("获取绝对路径" + file.getAbsolutePath());
System.out.println("获取文件名" + file.getName());
System.out.println("=====================list()=====================");
File file1 = new File("D:/");
String[] stringList = file1.list();
for (String string : stringList) {
System.out.println(string);
}
System.out.println("=====================listFile()=====================");
File[] files = file1.listFiles();
for (File file2 : files) {
System.out.println(file2.getName());
}
System.out.println("=====================FilenameFilter()=====================");
// 使用了 FilenameFilter 接口
File[] files1 = file1.listFiles((File dir, String name) -> name.equals("Game"));
for (File file2 : files1) {
System.out.println(file2);
}
递归显示文件夹
整体思路:获取到需要遍历的文件夹后,将目录中所有内容存入到
File数组中。遍历数组,如果被遍历的是文件夹则递归遍历,否则打印文件名。
public static void main(String[] args) {
recursionErgodic(new File("src\cn\john"), 0);
}
// 递归遍历
public static void recursionErgodic(File dir, int level) {
File[] files = dir.listFiles();
System.out.println(printSpace(level) + dir.getName());
level++;
if (files != null) {
// 遍历
for (File file : files) {
if (file.isDirectory()) {
recursionErgodic(file, level);
} else {
System.out.println(printSpace(level) + file.getName());
}
}
}
}
public static String printSpace(int level) {
return ("\t" + "|\").repeat(Math.max(0, level));
}
递归删除文件夹
整体思路:获取到需要遍历的文件夹后,将目录中所有内容存入到
File数组中。遍历数组,如果被遍历的是文件夹则递归遍历删除文件及文件夹,最终将最外层文件夹删除。
public static void recursionDelete(File dir) {
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
recursionDelete(file);
System.out.println(file.getName() + "->" + file.delete());
} else {
System.out.println(file.getName() + "->" + file.delete());
}
}
}
System.out.println(dir.getName() + "->" + dir.delete());
}
流
内存与存储设备之间传输数据的通道 ⽔借助管道传输;数据借助流传输。
流的分类
按方向
- 输入流:将存储设备中的内容读入到内存中。
- 输出流:将内存中的内容写到存储设备中。
按单位
- 字节流:以字节为单位,可以读写所有数据。
- 字符流:以字符为单位,只能读写⽂本数据。
按功能
- 节点流:具有实际传输数据的读写功能。
- 过滤流:在节点流的基础上增强功能。
节点流和过滤流都是Java中的输入流和输出流。区别在于,节点流是直接连接到数据源或目标的流,例如FileInputStream和FileOutputStream,它们可以直接操作文件。而过滤流则是建立在节点流的基础上,可以对节点流进行包装并提供额外的功能。例如,DatalnputStream和DataOutputStream可以读写基本数据类型, BufferedReader和BufferedWriter可以提供缓冲功能和按行读写等。因此,过滤流通常是节点流的补充和增强。
字节流
抽象类
- InputStream:字节输入流
public int read(){}public int read(byte[] b){}public int read(byte[] b, int off, int len){}
- OutputStream:字节输出流
public int write(){}public int write(byte[] b){}public int write(byte[] b, int off, int len){}
字节节点流
- FileInputStream:文件字节输入流
public int read(byte[] b)- 一次写多个字节,将b数组中所有字节,写入输入流。
- FileOutputStream:文件字节输出流
public int write(byte[] b)- 从流中读取多个字节,将读到内容存⼊b数组,返回实际读到的字节数。
- 如果达到文件的尾部,则返回**-1**。
// 字节输入流
public static void main(String[] args) throws Exception {
InputStream fis = new FileInputStream(new File("bcd.txt"));
// 读取单个字节
/*int data = fis.read();
System.out.println(data);*/
// 单字节循环读
int len;
while ((len = fis.read()) != -1) {
System.out.print((char) len + " ");
}
// 读取多字节
/*byte[] buffer = new byte[10];
while ((len = fis.read(buffer)) != -1) {
String s = new String(buffer, 0, len);
System.out.println(s);
}*/
fis.close();
}
// 字节输出流
public static void main(String[] args) throws Exception {
OutputStream fos = new FileOutputStream(new File("bcd.txt"), true);
// fos.write(97); // a
String s = "测\r\n";
for (int i = 0; i < 3; i++) {
fos.write(s.getBytes());
System.out.println(Arrays.toString(s.getBytes()));
}
byte[] te = {-26, -75, -117};
fos.write(te);
fos.close();
System.out.println("写入完成");
}
字节缓冲流
- BufferedOutputStream:字节输出缓冲流
- BufferedInputStream:字节输入缓冲流
- 提⾼IO效率,减少访问磁盘的次数。
- 数据存储在缓冲区中,flush是将缓冲区的内容写⼊⽂件中,也可以直接close。
// 字节输入缓冲流
public static void main(String[] args) throws Exception{
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("bcd.txt"));
int data;
while ((data = bufferedInputStream.read()) != -1) {
System.out.println(data);
}
bufferedInputStream.close();
}
// 字节输出缓冲流
public static void main(String[] args) throws Exception{
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("bcd.txt"));
String s = "疑是地上霜";
bos.write(s.getBytes());
bos.close();
}
对象流
- ObjectInutStream/ObjectOutputStream
- 增强了缓冲区功能
- 增强了读写8种基本数据类型和字符串功能
- 增强了读写对象的功能
readObject():从流中读取一个对象writeObject(Object obj):向流中写入一个对象
序列化
使用流传输对象的过程称为序列化和反序列化
- 序列化:把对象写入到硬盘或网络中的过程。
- 反序列化:把硬盘或网络中的二进制文件读取到内存形成对象的过程。
- 对象序列化的细节
- 序列化类及其对象属性必须实现
Serializable接口。 transient修饰为临时属性,不参与序列化。- 读取到文件尾部的标志:
java.io.EOFException。 - 使用
serialVersionUID属性保证序列化的类和反序列化的类是同一个类。
- 序列化类及其对象属性必须实现
public class TestStudent {
public static void main(String[] args) {
try {
serializableResult();
// serializableView();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 序列化
public static void serializableResult() throws Exception {
Student xm = new Student(3212, "john", 22);
Student xh = new Student(3214, "jack", 22);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("student.bin"));
// 1. 2.
// oos.writeObject(xm);
// oos.writeObject(xh);
ArrayList<Student> students = new ArrayList<>();
students.add(xm);
students.add(xh);
oos.writeObject(students);
oos.close();
}
// 反序列化
public static void serializableView() throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("student.bin"));
// 1.
// Object xm = ois.readObject();
// Object xh = ois.readObject();
//
// System.out.println(xm);
// System.out.println(xh);
// 2.
// try {
// while (true) {
// Object student = ois.readObject();
// System.out.println(student);
// }
// } catch (EOFException e) { // 通过捕获EOFException(读到文件尾的标志) -> 在不知道别人序列化存入几个对象的情况
// System.out.println("读取完毕");
// }
// 3.
ArrayList<Student> students = (ArrayList<Student>) ois.readObject();
System.out.println(students.toString());
ois.close();
}
}
字符编码
| 编码 | 说明 |
|---|---|
| ISO-8859-1 | 收录除ASCII外,还包括⻄欧、希腊语、泰语、阿拉伯语、希伯来语对应的⽂字符号。 |
| UTF-8 | 针对Unicode的可变⻓度字符编码。 |
| GB2312 | 简体中⽂。 |
| GBK | 简体中⽂、扩充。 |
| BIG5 | 台湾,繁体中⽂。 |
字符流
抽象类
- Reader:字符输入流
public int read(){}public int read(char\[] c){}public int read(char\[] b, int off, int len){}
- Writer:字符输出流
public void write(int n){}public void write(String str){}public void write(char\[] c){}
字符节点流
- FileWriter:
- public void write(String str)
- ⼀次写多个字符,将b数组中所有字符,写⼊输出流。
- FileReader:
- public int read(char[] c)
- 从流中读取多个字符,将读到内容存⼊c数组,返回实际读到的字符数;如果达到⽂件的尾部,则返回-1。
public static void main(String[] args) throws Exception {
Reader fr = new FileReader(new File("fw.txt"));
// 1.
char[] buf = new char[1024];
int len;
while ((len = fr.read(buf)) != -1) {
String s = new String(buf, 0, len);
System.out.println(s);
}
// 2.
int data;
while ((data = fr.read()) != -1) { // 25925 20065 30340 27185 33457
System.out.print((char) data); // 230 149 133
}
}
public static void main(String[] args) throws Exception {
FileWriter fw = new FileWriter(new File("fw.txt"));
// 1.
String s = "故乡的樱花";
fw.write(s);
// 2.
char[] c = {'故', '乡', '的', '樱', '花'};
fw.write(c);
fw.close();
}
字符缓冲流
BufferedWriter/BufferedReader
- 支持输入换行符
- 可一次写一行、读一行
| 方法 | 说明 |
|---|---|
| readLine() | 读一行 |
| newLine() | 换行 |
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new FileReader("fw.txt"));
String data;
while ((data = br.readLine()) != null) {
System.out.println(data);
}
br.close();
}
public static void main(String[] args) throws Exception {
BufferedWriter bw = new BufferedWriter(new FileWriter("fw.txt", false));
String data = "中国";
for (int i = 0; i < 5; i++) {
bw.write(data);
bw.newLine();
}
bw.close();
}
打印流
PrintWriter
- 封装了print() / println()⽅法,⽀持写⼊后换⾏。
- ⽀持数据原样打印。
// PrintStream和PrintWriter的使用
public static void main(String[] args) throws Exception {
PrintStream ps = new PrintStream("fw.txt");
PrintWriter pw = new PrintWriter("fw.txt");
ps.write(97); // 打印a
ps.println(97); // 打印97
pw.write(97);
pw.println(97);
ps.flush();
PrintStream ps2 = System.out;
ps2.println(97);
ps2.write(97);
ps2.flush();
}
// 设置out默认输出不为控制台 -> bcd.txt
// System.out 返回 PrintStream,但不能直接将打印流赋值给System.out,需要用setOut方法
public static void main(String[] args) throws Exception {
System.setOut(new PrintStream("bcd.txt"));
System.out.println("97");
System.out.println(97);
}
// System.in返回InputStream
public static void main(String[] args) throws Exception {
InputStream is = System.in;
BufferedReader br = new BufferedReader(new InputStreamReader(is));
System.out.println("请输入姓名");
String name = br.readLine();
System.out.println("请输入年龄");
String SAge = br.readLine();
int age = Integer.parseInt(SAge);
System.out.println("姓名:" + name + ",年龄:" + (age + 10));
}
转换流
InputStreamReader/OuputStreamWriter
- 可将字节流转换为字符流
- 可设置字符的编码方法
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("fw.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fis, StandardCharsets.UTF_8));
String data;
while ((data = br.readLine()) != null) {
System.out.println(data);
}
br.close();
}
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("fw.txt");
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos, StandardCharsets.UTF_8));
String data = "故宫";
for (int i = 0; i < 3; i++) {
bw.write(data);
bw.newLine();
}
bw.close();
}
Properties 集合
Properties:属性集合
特点:
- 存储属性名和属性值
- 属性名和属性值都是字符串类型
- 没有泛型
- 和流有关
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.setProperty("name", "john");
properties.setProperty("age", "18");
properties.setProperty("gender", "boy");
properties.list(System.out);
properties.store(new FileOutputStream("bcd.txt"), "john个人信息");
Properties properties1 = new Properties();
properties1.load(new FileInputStream("bcd.txt"));
properties1.list(System.out);
}