IO流
FileCopy
- 字节节点流拷贝文件(
FileInputStream
+FileOutputStream
):
1 | package com.f.chapter19.outputstream_; |
- 字节处理流拷贝文件(
BufferedInputStream
+BufferedOutputStream
):
1 | package com.f.chapter19.outputstream_; |
Reader
Reader
抽象类是所有字符输入流的父类:public abstract class Reader implements Readable, Closeable
。Reader
的常用子类:FileReader
:文件字符输入流。BufferedReader
:缓冲字符输入流。InputStreamReader
:转换输入流。
FileReader
public class FileReader extends InputStreamReader
public int read()
:每次读取单个字符,返回该字符,如果到文件末尾返回-1
。public int read(char cbuf[], int offset, int length)
:批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾则返回-1
。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32package com.f.chapter19.reader_;
import java.io.FileReader;
import java.io.IOException;
/**
* @author fzy
* @date 2023/7/10 20:18
* 演示FileReader的使用(字符输入流:文件 --> 程序)
*/
public class FileReader_ {
public static void main(String[] args) {
String filePath = "C:\\Users\\1\\Code Project\\Java project\\file\\hello.txt";
FileReader fileReader = null;
char[] buf = new char[8];
int readLen = 0;
try {
fileReader = new FileReader(filePath);
while ((readLen = fileReader.read(buf)) != -1) {
System.out.println(new String(buf, 0, readLen));
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
fileReader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
BufferedReader
public class BufferedReader extends Reader
。使用
BufferedReader
读取文本文件,并显示在控制台。将节点流作为参数传入处理流的构造器。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27package com.f.chapter19.reader_;
import java.io.BufferedReader;
import java.io.FileReader;
/**
* @author fzy
* @date 2023/7/11 15:26
* 使用 `BufferedReader` 读取文本文件,并显示在控制台。
*/
public class BufferedReader_ {
public static void main(String[] args) throws Exception {
String filePath = "C:\\Users\\1\\Code Project\\Java project\\javaedu\\src\\com\\f\\chapter10\\TestMainParam.java";
BufferedReader bufferedReader = null;
bufferedReader = new BufferedReader(new FileReader(filePath));
String line = null;
int cnt = 1;
//bufferedReader.readLine() 是按行读取文件。当返回 null 时,表示文件读取完毕。
while ((line = bufferedReader.readLine()) != null) {
System.out.print("读取第" + (cnt++) + "行:");
System.out.println(line);
}
//不要忘记关闭流。只需要关闭外层流即可,因为底层会去自动关闭节点流
bufferedReader.close();
}
}
InputStreamReader
public class InputStreamReader extends Reader
将字节流
FilelnputStream
包装成(转换成)字符流InputStreamReader
,对文件进行读取(按照gbk
格式),进而再包装成BufferedReader
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37package com.f.chapter19.transformation_;
import java.io.*;
/**
* @author fzy
* @date 2023/7/12 15:55
*/
public class InputStreamReader_ {
public static void main(String[] args) {
String filePath = "C:\\Users\\1\\Code Project\\Java project\\file\\note.txt";
InputStreamReader inputStreamReader = null;
BufferedReader bufferedReader = null;
String line = null;
try {
//将 FileInputStream(字节流) 包装成 InputStreamReader(字符流),并指定了编码为 gbk
inputStreamReader = new InputStreamReader(new FileInputStream(filePath), "gbk");
//把 InputStreamReader 传入 BufferedReader,以提高效率
bufferedReader = new BufferedReader(inputStreamReader);
////更简略的写法
//bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "gbk"));
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
bufferedReader.close(); //关闭最外层的流即可
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
Writer
Writer
抽象类是所有字符输出流的父类:public abstract class Writer implements Appendable, Closeable, Flushable
。Writer
的常用子类:FileWriter
:文件字符输出流。BufferedWriter
:缓冲字符输出流。OutputStreamWriter
:转换输出流。
FileWriter
public class FileWriter extends OutputStreamWriter
public void write(int c)
:将指定的字符写入文件,如果文件不存在,则创建该文件,下面的方法同理。public void write(char cbuf[])
:将cbuf.length
个字符从指定的字符数组写入文件。public void write(char cbuf[], int off, int len)
:将len
个字节从位于偏移量off
的指定字符数组写入此文件。public void write(String str)
:写入整个字符串。public void write(String str, int off, int len)
:写入字符串的指定部分。注意:
FileWriter
使用后,必须要关闭(close
)或刷新(flush
),否则写入不到指定的文件。因为在调用了fileWriter.flush();
或者fileWriter.close();
后,最终会调用OutputStream
的write
方法,该方法才真正将内容写入文件。1
2
3
4
5
6
7
8
9
10
11
12
13
14//OutputStream的write方法
public void write(byte b[], int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if ((off < 0) || (off > b.length) || (len < 0) ||
((off + len) > b.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return;
}
for (int i = 0 ; i < len ; i++) {
write(b[off + i]);
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34package com.f.chapter19.writer_;
import java.io.FileWriter;
import java.io.IOException;
/**
* @author fzy
* @date 2023/7/10 21:09
*/
public class FileWriter_ {
public static void main(String[] args) {
String filePath = "C:\\Users\\1\\Code Project\\Java project\\file\\note.txt";
FileWriter fileWriter = null;
char[] chars = {'h', 'd', 'l', 'g', 'd', 'x', '\n'};
try {
fileWriter = new FileWriter(filePath, true); //append置为true,表示追加
fileWriter.write('F'); //写入单个字符
fileWriter.write('\n'); //换行
fileWriter.write(chars); //写入字符数组
fileWriter.write(chars, 0, chars.length);
fileWriter.write("写入这一行\n"); //写入字符串
fileWriter.write("写入这一行的一部分", 0, 3); //将 “写入这” 写入了文件
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
fileWriter.close(); //必须要关闭(`close`)或刷新(`flush`),否则写入不到指定的文件。
} catch (IOException e) {
throw new RuntimeException(e);
}
System.out.println("程序结束...");
}
}
}
BufferedWriter
public class BufferedWriter extends Writer
。使用
BufferedWriter
将文本写入到文件中。将节点流作为参数传入处理流的构造器。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21package com.f.chapter19.writer_;
import java.io.BufferedWriter;
import java.io.FileWriter;
/**
* @author fzy
* @date 2023/7/11 15:49
*/
public class BufferedWriter_ {
public static void main(String[] args) throws Exception {
String filePath = "C:\\Users\\1\\Code Project\\Java project\\file\\note.txt";
BufferedWriter bufferedWriter = null;
bufferedWriter = new BufferedWriter(new FileWriter(filePath, true)); //append置为true表示追加
bufferedWriter.write("向文件中写入这一行...");
//写一行行分隔符。 行分隔符字符串由系统属性line.separator定义,并不一定是单个换行符('\n')字符。
bufferedWriter.newLine();
System.out.println("写入成功!");
bufferedWriter.close(); //关闭流
}
}
OutputStreamWriter
public class OutputStreamWriter extends Writer
将字节流
FileOutputStream
包装成(转换成)字符流OutputStreamWriter
,对文件进行写入(按照gbk
格式,也可以指定其他,比如utf-8
)。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30package com.f.chapter19.transformation_;
import java.io.*;
/**
* @author fzy
* @date 2023/7/12 16:21
*/
public class OutputStreamWriter_ {
public static void main(String[] args) {
String filePath = "C:\\Users\\1\\Code Project\\Java project\\file\\note.txt";
OutputStreamWriter outputStreamWriter = null;
String charSet = "gbk";
try {
outputStreamWriter = new OutputStreamWriter(new FileOutputStream(filePath), charSet);
outputStreamWriter.write("你好!");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
outputStreamWriter.close();
System.out.println("按照 " + charSet + " 编码方式保存文件成功!");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
PrintWriter
public class PrintWriter extends Writer
- 字符打印流
★序列化和反序列化
看下面两个需求:
- 将
int num=100
这个int
数据保存到文件中,注意不是100
数字,而是int 100
,并且能够从文件中直接恢复int 100
。 - 将
Dog dog=new Dog(“小黄”, 3)
这个dog
对像保存到文件中,并且能够从文件恢复。
上面的要求,就是能够将基本数据类型或者对象进行序列化和反序列化的操作。
- 将
序列化和反序列化:
- 序列化就是在保存数据时,保存数据的值和数据类型。
- 反序列化就是在恢复数据时,恢复数据的值和数据类型。
- 需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:
Serializable //这是一个标记接口,没有方法
-> 优先使用Externalizable //该接口有方法需要实现,一般使用 Serializable 接口
为了表示目录中
InputStream、OutputStream、Reader、Writer
及其子类的关系,所以ObjectInputStream
和ObjectOutputStream
仍然放在InputStream
、OutputStream
的目录下面。ObjectOutputStream
提供序列化的功能。ObjectInputStream
提供反序列化的功能。
★对象处理流的使用细节
- 读写顺序要一致。
- 要求序列化或反序列化的对象,其对应的类需要实现
Serializable
或Externalizable
接口。 - 序列化的类中建议添加
private static final long SerialVersionUID
,为了提高版本的兼容性。 - 序列化对象时,默认将里面所有属性都进行序列化,但除了
static
或transient
修饰的成员,即不会将这两种成员序列化保存到文件中。 - 序列化对象时,要求里面属性的类型也需要实现序列化接口。
- 序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化。
标准输入输出流
类型 | 默认设备 | |
---|---|---|
System.in 标准输入 | InputStream | 键盘 |
System.out 标准输出 | PrintStream | 显示器 |
System.in
的编译类型是InputStream
,运行类型是BufferedInputStream
。- 在
System
类中:public final static InputStream in = null;
- 在
System.out
的编译类型是PrintStream
,运行类型是PrintStream
。- 在
System
类中:public final static PrintStream out = null;
- 在
转换流
转换流是将字节流包装为字符流。
InputStreamReader
和OutputStreamWriter
InputStreamReader
:Reader
的子类,可以将InputStream
(字节流)包装成Reader
(字符流)。OutputStreamWriter
:Writer
的子类,实现将OutputStream
(字节流)包装成Writer
(字符流)。- 当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,所以建议将字节流转换成字符流。
- 可以在使用时指定编码格式(比如
utf-8
,gbk
,gb2312
,ISO8859-1
等)。
为了表示目录中
InputStream、OutputStream、Reader、Writer
及其子类的关系,所以InputStreamReader
和OutputStreamWriter
仍然放在Reader
、Writer
的目录下面。
打印流
PrintStream
字节打印流和PrintWriter
字符打印流。打印流只有输出流,没有输入流。
为了表示目录中
InputStream、OutputStream、Reader、Writer
及其子类的关系,所以PrintStream
和PrintWriter
仍然放在OutputStream
、Writer
的目录下面。
★Properties
接着“第十四章 集合”中,
Properties
的话题。Properties
是专门用于读写配置文件的集合类。1
2
3
4//配置文件的格式
键=值
键=值
...**注意:键值对不需要有空格,值不需要用引号引起来,默认类型是
String
**。Properties
的常见方法:public synchronized void load(Reader reader)
、public synchronized void load(InputStream inStream)
:加载配置文件的键值对到Properties
对象。public void list(PrintStream out)
:将数据显示到指定设备 / 流对象。getProperty(key)
:根据键获取值。setProperty(key, value)
:设置键值对到Properties
对象。-> 若key
存在则修改,不存在则添加。public void store(Writer writer, String comments)
:将Properties
中的键值对存储到配置文件,在idea
中,保存信息到配置文件,如果含有中文,会存储为unicode
码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34package com.f.chapter19.properties_;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
/**
* @author fzy
* @date 2023/7/12 20:03
*/
public class Properties_ {
public static void main(String[] args) {
//使用 Properties 类来读取 mysql.peoperties 文件
String filePath = "C:\\Users\\1\\Code Project\\Java project\\file\\mysql.properties";
Properties properties = new Properties();
try {
//1.`load`:加载配置文件的键值对到 `Properties` 对象。
properties.load(new FileReader(filePath));
//2.`list`:将数据显示到指定设备 / 流对象。
properties.list(System.out);
//3.`getProperty(key)`:根据键获取值。
System.out.println("用户名 = " + properties.getProperty("user"));
System.out.println("密码 = " + properties.getProperty("pwd"));
//4.`setProperty(key, value)`:设置键值对到 `Properties` 对象。
properties.setProperty("charset", "utf-8");
//5.`store`:将 `Properties` 中的键值对存储到配置文件,在 `idea` 中,保存信息到配置文件,如果含有中文,会存储为 `unicode` 码。
properties.store(new FileWriter(filePath), "This is a comment.");
System.out.println("保存配置文件成功!");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}