区分输入输出流 针对内存
- 流:数据在数据源(文件)和程序(内存)之间经历的路径
- 输入流:数据从数据源(文件)到程序(内存)的路径
- 输出流:数据从程序(内存)到数据源(文件)的路径
- new File(String pathname)//根据路径构建一个File对象
- new File(File parent,String child)//根据父目录文件+子路径构建
- new File(String parent,String child)//根据父目录+子路径构建
- createNewFile() 创建新文件
注意:new File只是在java内存中产生文件,真正在磁盘中产生还得使用file.createNewFile()
代码案例
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
package com.zjh;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.IOException;
public class FileCreate {
public static void main(String[] args) {
}
//方式1 new File(String pathname)
@Test
public void create01() {
String filePath = "d:\\news1.txt";
File file = new File(filePath);
try {
file.createNewFile();
System.out.println("文件创建成功");
} catch (IOException e) {
e.printStackTrace();
}
}
//方式2 new File(File parent,String child) //根据父目录文件+子路径构建
//e:\\news2.txt
@Test
public void create02() {
File parentFile = new File("d:\\");
String fileName = "news2.txt";
//这里的file对象,在java程序中,只是一个对象
//只有执行了createNewFile 方法,才会真正的,在磁盘创建该文件
File file = new File(parentFile, fileName);
try {
file.createNewFile();
System.out.println("创建成功~");
} catch (IOException e) {
e.printStackTrace();
}
}
//方式3 new File(String parent,String child) //根据父目录+子路径构建
@Test
public void create03() {
//String parentPath = "e:\\";
String parentPath = "d:\\";
String fileName = "news4.txt";
File file = new File(parentPath, fileName);
try {
file.createNewFile();
System.out.println("创建成功~");
} catch (IOException e) {
e.printStackTrace();
}
}
}
|
基本api
- getName 文件名
- getAbsolutePath 绝对路径
- getParent 父目录
- length 长度
- exists 是否存在
- isFile 是否文件
- isDirectory 是否目录
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
|
package com.zjh;
import org.junit.jupiter.api.Test;
import java.io.File;
public class FileInformation {
public static void main(String[] args) {
}
//获取文件的信息
@Test
public void info() {
//先创建文件对象
File file = new File("d:\\news1.txt");
//调用相应的方法,得到对应信息
System.out.println("文件名字=" + file.getName());
//getName、getAbsolutePath、getParent、length、exists、isFile、isDirectory
System.out.println("文件绝对路径=" + file.getAbsolutePath());
System.out.println("文件父级目录=" + file.getParent());
System.out.println("文件大小(字节)=" + file.length());
System.out.println("文件是否存在=" + file.exists());//T
System.out.println("是不是一个文件=" + file.isFile());//T
System.out.println("是不是一个目录=" + file.isDirectory());//F
}
}
|
- mkdir创建一级目录
- mkdirs创建多级目录
- delete删除空目录或文件(delete删除一个目录时,需要确保该目录下面没有文件或者子目录,否则需要先删除文件和字目录)
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
package com.zjh;
import org.junit.jupiter.api.Test;
import java.io.File;
public class Directory_ {
//判断 d:\\news1.txt 是否存在,如果存在就删除
@Test
public void m1() {
String filePath = "d:\\news1.txt";
File file = new File(filePath);
if (file.exists()) {
if (file.delete()) {
System.out.println(filePath + "删除成功");
} else {
System.out.println(filePath + "删除失败");
}
} else {
System.out.println("该文件不存在...");
}
}
//判断 D:\\demo02 是否存在,存在就删除,否则提示不存在
//这里我们需要体会到,在java编程中,目录也被当做文件
@Test
public void m2() {
String filePath = "D:\\demo02";
File file = new File(filePath);
if (file.exists()) {
if (file.delete()) {
System.out.println(filePath + "删除成功");
} else {
System.out.println(filePath + "删除失败");
}
} else {
System.out.println("该目录不存在...");
}
}
//判断 D:\\demo\\a\\b\\c 目录是否存在,如果存在就提示已经存在,否则就创建
@Test
public void m3() {
String directoryPath = "D:\\demo\\a\\b\\c";
File file = new File(directoryPath);
if (file.exists()) {
System.out.println(directoryPath + "存在..");
} else {
if (file.mkdirs()) { //创建一级目录使用mkdir() ,创建多级目录使用mkdirs()
System.out.println(directoryPath + "创建成功..");
} else {
System.out.println(directoryPath + "创建失败...");
}
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public static void main(String[] args) {
String filePath = "D:\\demo02";
File file = new File(filePath);
deleteAll(file);
}
//递归删除非空目录
public static void deleteAll(File file){
if (file.exists()) {
File files[] = file.listFiles();
int len = files.length;
for (int i = 0; i < len; i++) {
if (files[i].isDirectory()) {
deleteAll(files[i]);
} else {
files[i].delete();
}
}
file.delete();
}
}
|

- input:读取外部数据到内存(程序)
- output:将内存(程序)数据输出到外部储存设备中
作用:读写文件、网络通讯
- 按操作数据单位不同分为:字节流(8 bit)【二进制文件】,字符流(按字符)【文本文件】
注意:处理文本用字符流,而处理图片、视频等二进制文件最好使用字节流,否则可能会造成损失
- 按数据流的流向不同分为:输入流,输出流
- 按流的角色的不同分为:节点流,处理流(包装/装饰流)
四个基本抽象基类
|
字节流 |
字符流 |
输入流 |
Inputstream |
Reader |
输出流 |
Onputstream |
Writer |
派生子类一般都以父类名作为子类后缀
总览:

- FileInputStream:文件输入流
- BufferedInputStream:缓存字节输入流
- ObjectedInputStream:对象字节输入流
主要方法:
创建:
- FileInputStream(String FilePath)
- FileInputStream(File file)
读取:
- public int read()
- 返回读取的字节
- 一次读取一个字节,效率低
- 可以转化为char显示字符
- 读取中文会乱码(3字节)
- public int read(byte[] b)
- 一次读取一个字节数组长度的数据
- 返回读取的字节数量
- 读取中文如果是截断读取会乱码,如果刚好都在一个字节数组中读取出来,才不会乱码
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
package com.zjh;
import org.junit.jupiter.api.Test;
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStream_ {
public static void main(String[] args) {
}
/**
* 演示读取文件...
* 单个字节的读取,效率比较低
* -> 使用 read(byte[] b)
*/
@Test
public void readFile01() {
String filePath = "C:\\Users\\Mono\\Desktop\\a.txt";
int readData = 0;
FileInputStream fileInputStream = null;
try {
//创建 FileInputStream 对象,用于读取 文件
fileInputStream = new FileInputStream(filePath);
//从该输入流读取一个字节的数据。 如果没有输入可用,此方法将阻止。
//如果返回-1 , 表示读取完毕
while ((readData = fileInputStream.read()) != -1) {
System.out.print((char)readData);//转成char显示
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭文件流,释放资源.
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 使用 read(byte[] b) 读取文件,提高效率
*/
@Test
public void readFile02() {
String filePath = "C:\\Users\\Mono\\Desktop\\a.txt";
//字节数组
byte[] buf = new byte[8]; //一次读取8个字节.中文截断 byte[30]则完整输出
int readLen = 0;
FileInputStream fileInputStream = null;
try {
//创建 FileInputStream 对象,用于读取 文件
fileInputStream = new FileInputStream(filePath);
//从该输入流读取最多b.length字节的数据到字节数组。 此方法将阻塞,直到某些输入可用。
//如果返回-1 , 表示读取完毕
//如果读取正常, 返回实际读取的字节数
while ((readLen = fileInputStream.read(buf)) != -1) {
System.out.print(new String(buf, 0, readLen));//显示
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭文件流,释放资源.
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
|
主要方法:
创建:
- FileOutputStream(String FilePath , boolean append)
- FileOutputStream(File file , boolean append)
append为true表示追加模式,为false为覆盖,默认false
写入:当文件不存在,会自动创建(前提是目录存在)
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
37
38
39
40
41
42
43
44
|
package com.zjh;
import org.junit.jupiter.api.Test;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStream_ {
public static void main(String[] args) {
}
@Test
public void writeFile() {
//创建 FileOutputStream对象
String filePath = "d:\\a.txt";
FileOutputStream fileOutputStream = null;
try {
//得到 FileOutputStream对象 对象
//老师说明
//1. new FileOutputStream(filePath) 创建方式,当写入内容是,会覆盖原来的内容
//2. new FileOutputStream(filePath, true) 创建方式,当写入内容是,是追加到文件后面
fileOutputStream = new FileOutputStream(filePath, true);
//写入一个字节
// fileOutputStream.write('H');//
//写入字符串
String str = "hsp,world!";
//str.getBytes() 可以把 字符串-> 字节数组
fileOutputStream.write(str.getBytes());
/*
write(byte[] b, int off, int len) 将 len字节从位于偏移量 off的指定字节数组写入此文件输出流
*/
// fileOutputStream.write(str.getBytes(), 0, 3);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
|
注意:要使用fileOutputStream.write(buf,0,readLen);
,否则对于图片等文件可能会导致写入多余文件而失效
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
37
38
|
package com.zjh;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileCopy {
public static void main(String[] args) {
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
String filePath = "d:\\pic.png";
String descPath = "d:\\pic2.png";
try {
fileInputStream = new FileInputStream(filePath);
fileOutputStream = new FileOutputStream(descPath);
byte[] buf = new byte[1024];
int readLen = 0;
while((readLen = fileInputStream.read(buf)) != -1){
fileOutputStream.write(buf,0,readLen);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(fileInputStream != null){
fileInputStream.close();
}
if(fileOutputStream != null){
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
|
字符流可以方便处理字符文件
创建
FileReader(String/File)
读取
- public int read()
- 返回读取的字符
- 一次读取一个字符,效率低
- 可以转化为char显示字符
- public int read(char[] b,int off ,int len)
- 一次读取一个字符数组长度的数据
- 返回读取的字符数量
- 起始off下标 ,len开始
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
package com.zjh;
import org.junit.jupiter.api.Test;
import java.io.FileReader;
import java.io.IOException;
public class FileReader_ {
public static void main(String[] args) {
}
/**
* 单个字符读取文件
*/
@Test
public void readFile01() {
String filePath = "d:\\a.txt";
FileReader fileReader = null;
int data = 0;
//1. 创建FileReader对象
try {
fileReader = new FileReader(filePath);
//循环读取 使用read, 单个字符读取
while ((data = fileReader.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileReader != null) {
fileReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 字符数组读取文件
*/
@Test
public void readFile02() {
System.out.println("~~~readFile02 ~~~");
String filePath = "d:\\a.txt";
FileReader fileReader = null;
int readLen = 0;
char[] buf = new char[8];
//1. 创建FileReader对象
try {
fileReader = new FileReader(filePath);
//循环读取 使用read(buf), 返回的是实际读取到的字符数
//如果返回-1, 说明到文件结束
while ((readLen = fileReader.read(buf)) != -1) {
System.out.print(new String(buf, 0, readLen));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileReader != null) {
fileReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
|
注意一定要close( ),或者flush( )进行,否则无法写入文件
- close( )、flush( )的底层都使用了OutPutStream的write( )方法写入
- close = flush + 关闭
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
37
38
39
40
41
|
package com.zjh;
import java.io.FileWriter;
import java.io.IOException;
public class FileWriter_ {
public static void main(String[] args) {
String filePath = "d:\\note.txt";
//创建FileWriter对象
FileWriter fileWriter = null;
char[] chars = {'a', 'b', 'c'};
try {
fileWriter = new FileWriter(filePath);//默认是覆盖写入
// 3) write(int):写入单个字符
fileWriter.write('H');
//// 4) write(char[]):写入指定数组
fileWriter.write(chars);
//// 5) write(char[],off,len):写入指定数组的指定部分
fileWriter.write("韩顺平教育".toCharArray(), 0, 3);
// 6) write(string):写入整个字符串
fileWriter.write(" 你好北京~");
fileWriter.write("风雨之后,定见彩虹");
//// 7) write(string,off,len):写入字符串的指定部分
fileWriter.write("上海天津", 0, 2);
//在数据量大的情况下,可以使用循环操作.
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//fileWriter.flush();
//关闭文件流,等价 flush() + 关闭
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("程序结束...");
}
}
|
文件不存在会创建文件(前提:目录存在)
String.toCharArray()
总览
分类 |
字节输入 |
字节输出 |
字符输入 |
字符输出 |
抽象基类 |
InputStream |
OutputStream |
Reader |
Writer |
访问文件 |
FileInputStream |
FileOutputStream |
FileReader |
FileWriter |
访问数组 |
ByteArrayInputStream |
ByteArrayOutputStream |
CharArrayReader |
CharArrayWriter |
访问管道 |
PipedInputStream |
PipedOutputStream |
PipedReader |
PipedWriter |
访问字符串 |
|
|
StringReader |
StringWriter |
以下是处理流 |
|
|
|
|
缓存流 |
BufferedInputStream |
BufferedOutputStream |
BufferedReader |
BufferedWriter |
转换流 |
|
|
InputStreamReader |
OutputStreamReader |
对象流 |
ObjectInputStream |
ObjectOutputStream |
|
|
过滤流 |
FilterInputStream |
FilterOutputStream |
|
|
打印流 |
|
PrintStream |
|
PrintWriter |
推回输入流 |
PushbackInputStream |
|
PushbackInputReader |
|
特殊流 |
DataInputStream |
DataOutputStream |
|
|
节点流:直接与数据源相连,读入或读出。
直接使用节点流,读写不方便,为了更快的读写文件,才有了处理流。
- 父 类 :InputStream 、OutputStream、 Reader、 Writer
- 文 件 :FileInputStream 、 FileOutputStream 、FileReader 、FileWriter 文件进行处理的节点流
- 数 组 :ByteArrayInputStream、 ByteArrayOutputStream、 CharArrayReader 、CharArrayWriter 对数组进行处理的节点流(对应的不再是文件,而是内存中的一个数组)
- 字符串 :StringReader、 StringWriter 对字符串进行处理的节点流
- 管 道 :PipedInputStream 、PipedOutputStream 、PipedReader 、PipedWriter 对管道进行处理的节点流
处理流和节点流一块使用,在节点流的基础上,再套接一层,套接在节点流上的就是处理流。如BufferedReader
处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。装饰者模式
注意:使用处理流时只需要关闭处理流,不需要手动关闭节点流,处理流close底层默认会关闭节点流
- 缓冲流:BufferedInputStream 、BufferedOutputStream、 BufferedReader、 BufferedWriter 增加缓冲功能,避免频繁读写硬盘。
- 转换流:InputStreamReader 、OutputStreamReader实现字节流和字符流之间的转换。
- 数据流: DataInputStream 、DataOutputStream 等-提供将基础数据类型写入到文件中,或者读取出来。
创建:
BufferedReader (Reader in)
创建使用默认人小的输入缓冲区的缓冲字符输入流。
读取:
public String readLine()
读取到末尾则返回null
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package com.zjh;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferReader_ {
public static void main(String[] args) throws IOException {
String filePath = "d:\\a.txt";
//创建bufferedReader
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
//读取
String line; //按行读取, 效率高
//说明
//1. bufferedReader.readLine() 是按行读取文件
//2. 当返回null 时,表示文件读取完毕
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
bufferedReader.close();
}
}
|
创建:
BufferedWriter (Writer out)
写入:
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
|
package com.zjh;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWriter_ {
public static void main(String[] args) throws IOException {
String filePath = "d:\\ok.txt";
//创建BufferedWriter
//说明:
//1. new FileWriter(filePath, true) 表示以追加的方式写入
//2. new FileWriter(filePath) , 表示以覆盖的方式写入
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath));
bufferedWriter.write("hello, 韩顺平教育!");
bufferedWriter.newLine();//插入一个和系统相关的换行
bufferedWriter.write("hello2, 韩顺平教育!");
bufferedWriter.newLine();
bufferedWriter.write("hello3, 韩顺平教育!");
bufferedWriter.newLine();
//说明:关闭外层流即可 , 传入的 new FileWriter(filePath) ,会在底层关闭
bufferedWriter.close();
}
}
|
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
|
package com.zjh.Buffer;
import java.io.*;
public class BufferCopy {
public static void main(String[] args) {
String fromPath = "d:\\a.txt";
String toPath = "d:\\a2.txt";
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new FileReader(fromPath));
bw = new BufferedWriter(new FileWriter(toPath));
String line;
while ((line = br.readLine()) != null){
bw.write(line);
bw.newLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(br != null){
br.close();
}
if(bw != null){
bw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
|
API基本与FileInputStream&FileOutputStream没啥区别,这里省略
可以看到写法基本与上文3.1.3一致,但是效率会更高
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
|
package com.zjh.Buffer;
import java.io.*;
public class BufferStreamCopy {
public static void main(String[] args) {
String fromPath = "d:\\pic.png";
String toPath = "d:\\pic2.png";
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(fromPath));
bos = new BufferedOutputStream(new FileOutputStream(toPath));
byte[] buf = new byte[1024];
int readLen = 0;
while ((readLen = bis.read(buf)) != -1){
bos.write(buf,0,readLen);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(bis != null){
bis.close();
}
if(bos != null){
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
|
需求:将int num=100数据存放到文件中,读出时可以知道数据内容以及数据类型
- 序列化就是在保存数据时,保存数据的值和数据类型
- 反序列化就是在恢复数据时,恢复数据的直和数据类型
需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:
- Serializable 这是一个标记接口 【推荐】 空接口,无方法
- Externalizable 用于自定义哪些属性的序列化
使用ObjectOutputStream序列化基本数据类型和一个Dog对象(name, age),并保存到data.dat 文件中
注意:
- 建议在序列化的类中添加serialVersionUID,表示序列化的版本号,可以提高兼容性,即在版本升级时反序列化仍保持对象的唯一性。
- 在Dog改变时,系统会认为是修改而不是认为是一个全新的类
- 使用Serializable默认序列化所有属性,但是除了static以及transient修饰的属性
- 从结果可以看到是null
- 序列化对象时,要求里面属性的类型也需要实现序列化接口
- 如下面Dog类中的master类对象如果没有实现序列化接口,编译会出错
- 序列化具有可继承性,父类序列化,子类默认也序列化
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
37
38
39
40
|
package com.zjh;
import java.io.Serializable;
public class Dog implements Serializable {
private String name;
private int age;
//序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员
private static String nation;
private transient String color;
//序列化对象时,要求里面属性的类型也需要实现序列化接口
//serialVersionUID 序列化的版本号,可以提高兼容性
private static final long serialVersionUID = 1L;
//序列化对象时,要求里面属性的类型也需要实现序列化接口
private Master master = new Master();
public Dog(String name, int age, String nation, String color) {
this.name = name;
this.age = age;
this.color = color;
this.nation = nation;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
", color='" + color + '\'' +
'}' + nation ;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
|
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
|
package com.zjh.Object;
import com.zjh.Dog;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class ObjectOutStream_ {
public static void main(String[] args) throws IOException {
//序列化后,保存的文件格式,不是存文本,而是按照他的格式来保存
String filePath = "d:\\data.dat";
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
//序列化数据到 d:\data.dat
oos.writeInt(100);// int -> Integer (实现了 Serializable)
oos.writeBoolean(true);// boolean -> Boolean (实现了 Serializable)
oos.writeChar('a');// char -> Character (实现了 Serializable)
oos.writeDouble(9.5);// double -> Double (实现了 Serializable)
oos.writeUTF("韩顺平教育");//String
//保存一个dog对象
oos.writeObject(new Dog("旺财", 10, "日本", "白色"));
oos.close();
System.out.println("数据保存完毕(序列化形式)");
}
}
|
注意
- 读取的顺序要和写入的顺序一致,否则会乱码
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
37
38
39
|
package com.zjh.Object;
import com.zjh.Dog;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class ObjectInputStream_ {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//指定反序列化的文件
String filePath = "d:\\data.dat";
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
//读取
//老师解读
//1. 读取(反序列化)的顺序需要和你保存数据(序列化)的顺序一致
//2. 否则会出现异常
System.out.println(ois.readInt());
System.out.println(ois.readBoolean());
System.out.println(ois.readChar());
System.out.println(ois.readDouble());
System.out.println(ois.readUTF());
//dog 的编译类型是 Object , dog 的运行类型是 Dog
Object dog = ois.readObject();
System.out.println("运行类型=" + dog.getClass());
System.out.println("dog信息=" + dog);//底层 Object -> Dog
//这里是特别重要的细节:
//1. 如果我们希望调用Dog的方法, 需要向下转型
//2. 需要我们将Dog类的定义,放在到可以引用的位置
Dog dog2 = (Dog)dog;
System.out.println(dog2.getName()); //旺财..
//关闭流, 关闭外层流即可,底层会关闭 FileInputStream 流
ois.close();
}
}
|
System.in 编译InputStream 运行BufferInputStream 键盘输入
System.Out 编译运行PrintStream 显示器
Scanner里面放的就是输入流
1
2
3
4
|
Scanner scanner = new Scanner(System.in);
System.out.println("输入内容");
String next = scanner.next();
System.out.println("next=" + next);
|
- InputStreamReader:Reader的子类,可以将InputStream字节流(包装)转换为Reader字符流
- OutputStreamWriter:Writer的子类,可以将OutputStream字节流(包装)转换为Writer字符流
可以指定读取的编码格式和输出的编码格式
需求分析:读取一个编码格式为gbk的文本文件,使用FileInputStream只能按照默认的utf-8格式读取,会导致乱码,这时候就需要指定编码
InputStreamReader(Inputstream in,Charset cs) //创建使用给定字符集的
public String getEncoding() 返回此流使用的字符编码的名称。
gbk编码文件,使用utf-8读取

再使用InputStreamReader(Inputstream in,Charset cs)转换
使用使用BufferedReader提高读取效率
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
package com.zjh.transformation;
import java.io.*;
public class InputStreamReader_ {
public static void main(String[] args) throws IOException {
String filePath = "d:\\a.txt";
String charset = "gbk";
//使用FileInputStream读取文件
//使用InputStreamReader将字节流转为指定编码的字符流
//使用BufferedReader提高读取效率
BufferedReader br = new BufferedReader(
new InputStreamReader(
new FileInputStream(filePath),charset));
String s = br.readLine();
System.out.println(s);
//关闭最外层即可
br.close();
}
}
|

成功
将字节流FileOutputStream包装成(转换成)字符流OutputStreamWriter,对文件进行写入(按照gbk格式,可以指定其他,比如utf-8)
同样使用BufferedWriter提高效率
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package com.zjh.transformation;
import java.io.*;
public class OutputStreamWriter_ {
public static void main(String[] args) throws IOException {
String filePath = "d:\\hsp.txt";
String charSet = "gbk";
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath), charSet));
bw.write("hi, 韩顺平教育");
bw.close();
System.out.println("按照 " + charSet + " 保存文件成功~");
}
}
|
打印流只有输出流没有输入流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
package com.zjh.print;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
public class PrintStream_ {
public static void main(String[] args) throws IOException {
PrintStream out = System.out;
out.print("sda手打");
out.write("张俊鸿".getBytes());
out.close();
System.setOut(new PrintStream("d:\\hh.txt"));
PrintStream out2 = System.out;
out2.println("的阖家安康和接口大");
out2.close();
}
}
|
System.out是标准输出流 可以用PrintStream out接收
out.print(); 和out.write();的区别:
- 本质都是字节流的write()方法,print多了一层判空
默认输出位置是控制台
可以使用System.setOut改变输出位置,传入PrintStream("Path"/File)打印到文本文件中
1
2
3
4
5
6
|
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
package com.zjh.print;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class PrintWriter_ {
public static void main(String[] args) throws IOException {
PrintWriter printWriter = new PrintWriter(new FileWriter("d:\\f2.txt"));
printWriter.print("hi, 北京你好~~~~");
printWriter.close();//flush + 关闭流, 才会将数据写入到文件..
}
}
|
注意:一定要printWriter.close()或者flush(),否则不会写入,底层close()才真正调用write
读取配置文件
传统方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
package com.zjh.Properties;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class Properties01 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("src\\mysql.properties"));
String line = "";
while ((line = br.readLine())!=null){
String[] split = line.split("=");
//如果我们要求指定的ip值
if("ip".equals(split[0])) {
System.out.println(split[0] + "值是: " + split[1]);
}
}
br.close();
}
}
|
读取遍历,修改也麻烦
使用Properties类方便
读取key=value格式,不能有空格,值也不需要引号,默认类型是String
方法
- load:加载配置文件的键值对到Properties对象
- list:将数据显示到指定设备
- getProperty(key):根据键获取值
- setProperty(key,value):设置键值对到Properties对象
- store:将Properties中的键值对存储到配置文件,在idea中,保存信息到配置文件,如果含有中文,会存储为unicode码
注意如果是想将读取的String类型转为int或者其他,要用包装类
int age = Integer.parseInt(pro.getProperty("age"));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package com.zjh.Properties;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
public class Properties02 {
public static void main(String[] args) throws IOException {
//使用Properties 类来读取mysql.properties 文件
//1. 创建Properties 对象
Properties properties = new Properties();
//2. 加载指定配置文件
properties.load(new FileReader("src\\mysql.properties"));
//3. 把k-v显示控制台
properties.list(System.out);
//4. 根据key 获取对应的值
String user = properties.getProperty("user");
String pwd = properties.getProperty("pwd");
System.out.println("用户名=" + user);
System.out.println("密码是=" + pwd);
}
}
|
- properties.setProperty(key,value);
- properties.store(OutputStream/Writer,Comment);
- 使用OutputStream,如果有中文则在配置文件中以unicode编码写出,使用Writer就直接显示中文
- Comment在配置文件顶部写注释用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
package com.zjh.Properties;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
public class Properties03 {
public static void main(String[] args) throws IOException {
//使用Properties 类来创建 配置文件, 修改配置文件内容
Properties properties = new Properties();
properties.setProperty("charset", "utf8");
properties.setProperty("user", "汤姆");//注意保存时,是中文的 unicode码值
properties.setProperty("pwd", "888888");
//将k-v 存储文件中即可
// properties.store(new FileOutputStream("src\\mysql2.properties"), "注释");
properties.store(new FileWriter("src\\mysql2.properties"), "注释");
System.out.println("保存配置文件成功~");
}
}
|
开发中使用封装好的Commons IO类可以简化代码
工具包
网址跳转:链接