【561-597】IO流
2022-02-01 18:40:00 # JavaSE

概述

什么是 IO ?

I : Input
O : Output
通过IO以完成硬盘文件的读和写。

IO流的分类

  1. 按照流的方向进行分类: 以内存作为参照物,往内存中去,叫做输入(Input)或读(Read)。从内存中出来,叫做输出(output)或写(write)
  2. 按照读取数据方式的不同:按照字节的方式读取数据,一次读取1个字节byte,万能方式。按照字符的方式读取数据,一次读取一个字符。两者有在“中文(2字节)”“英文(1字节)”的区分

关于流

  1. 所有的流都在:Java.io.*; 下
  2. IO流四大家族:
    java.io.InputStream 字节输入流
    java.io.OutputStream 字节输出流
    java.io.Reader 字符输入流
    java.io.Writer 字符输出流
    Stream结尾的都是字节流,Reader/Writer都是字符流
  3. 所有的流都实现了Closable接口,有close()
  4. 所有的输出流都实现了Flushable接口,flush(),意味刷新输出管道,在最终输出后一定要flush(),否则可能丢失数据
  5. 需要掌握的流:
    文件专属流:
    java.io.FileInputStream
    java.io.FileOutputStream
    java.io.FileReader
    java.io.FileWriter
    转换流:(将字节流转换成字符流)
    java.io.InputStreanReader
    java.io.OutputStreamWriter
    缓冲流专属:
    java.io.BufferedReader
    java.io.BufferedWriter
    java.io.BufferedInputStream
    java.io.BufferedOutputStream
    数据流专属:
    java.io.DataInputStream
    java.io.DataOutputStream
    标准输出流:
    java.io.PrintWriter
    java.io.PrintStream
    对象专属流:
    java.io.ObjectInputStream
    java.io.ObjectOutputStream

文件专属流

FileInputStream

public int read() throws IOException

一个一个字节读入

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
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class _567_FileInputStream初步 {
public static void main(String[] args) {
FileInputStream f1 = null;
try {
// 打开文件
f1 = new FileInputStream("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_567_FileInputStream初步01.txt");
// f1 中的内容 "abbsbss"

// 循环读取文件,
int readData;
while((readData = f1.read()) != -1){
System.out.println(readData);
}
//

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try { // 可能 f1 = null
f1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

public int read(byte b[]) throws IOException

一次读入byte[]长度的字节

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
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class _569_IDEA中的当前路径 {
public static void main(String[] args) {
FileInputStream f1 = null;
try {
// 相对路径
// 默认当前路径是Project的根
f1 = new FileInputStream("【561-597】IO流\\src\\_567_FileInputStream初步01.txt");
// f1 文件中 "abbsbss";

//
byte[] bytes = new byte[4];
int readCount1 = f1.read(bytes); // 返回读到字节数量
System.out.println(readCount1); // 4
// 读入了前4个字节,"abbs"
System.out.println(new String(bytes)); // abbs
System.out.println(" ====================== ");

int readCount2 = f1.read(bytes);
System.out.println(readCount2); // 3
// 读入时,会将数据覆盖到原来的bytes数组上,这里覆盖前3个
// bytes[] = {a,b,b,s} 变为了 {b,s,s,s}
// 也就是覆盖了前3个
// System.out.println(new String(bytes)); // bsss
System.out.println(new String(bytes,0,readCount2)); // bss

System.out.println(" ====================== ");

int readCount3 = f1.read(bytes);
System.out.println(readCount3); // -1
System.out.println(" ====================== ");


} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
f1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

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
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class _571_FileInputStream最终版 {
public static void main(String[] args) {
FileInputStream f1 = null;
try {
f1 = new FileInputStream("【561-597】IO流\\src\\_567_FileInputStream初步01.txt");

int readCount;
byte[] bytes = new byte[4];
while ((readCount = f1.read(bytes)) != -1){
System.out.print(new String(bytes,0,readCount));
}
// "abbsbss"

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
f1.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}
}


public int available() throws IOException

返回剩下多少个字节没有读入

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
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class _572_FileInputStream其他常用方法 {
public static void main(String[] args) {
FileInputStream f1 = null;
try {
f1 = new FileInputStream("【561-597】IO流\\src\\_567_FileInputStream初步01.txt");

// 剩下多少个字节没有读入
System.out.println(f1.available()); // 7
byte[] bytes = new byte[f1.available()];
int readCount = f1.read(bytes);
System.out.println(new String(bytes,0,readCount));
// abbsbss

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
f1.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}
}

public long skip(long n) throws IOException

跳过多少个字节开始读

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
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class _573_skip方法 {
public static void main(String[] args) {
FileInputStream f1 = null;
try {
f1 = new FileInputStream("【561-597】IO流\\src\\_567_FileInputStream初步01.txt");
// abbsbss

// 跳过多少个字节开始读
f1.skip(3);

int read = f1.read();
System.out.println((char) read); // s

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
f1.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}
}

FileOutputStream

public void write(byte b[]) throws IOException

FileOutputStream 的构造方法可以实现不回清空源文件内容以追加的方式在文件末尾写入
append = true则可以实现

1
2
public FileOutputStream(String name, boolean append)
throws FileNotFoundException
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
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class _574_FileOutputStream的使用 {
public static void main(String[] args) {
FileOutputStream f1 = null;
try {
// 以追加的方式在文件末尾写入
// 不回清空源文件内容
f1 = new FileOutputStream("【561-597】IO流\\src\\_574_FileOutputStream的使用.txt",true);

byte[] bytes = {97,98,99,100};
f1.write(bytes);

// 写完后 一定要刷新
f1.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
f1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

使用 FileInputStream 和 FileOutputStream 完成文件拷贝

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
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class _575_文件复制 {
public static void main(String[] args) {
FileInputStream fin = null;
FileOutputStream fout = null;
try {
fin = new FileInputStream("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_575_文件复制01.txt");
fout = new FileOutputStream("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_575_文件复制02.txt",true);

byte[] bytes = new byte[1024*1024]; // 每次最多拷贝1MB
int readCount;
while((readCount = fin.read(bytes)) != -1){
fout.write(bytes,0,readCount);
}

// 一定要flush()
fout.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 两个文件能关就关,分开try
if (fin != null){
try {
fin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fout != null){
try {
fout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

}
}

FileReader

public int read(char cbuf[]) throws IOException

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
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class _576_FileReader的使用 {
public static void main(String[] args) {
FileReader f1 = null;
try {
f1 = new FileReader("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_576_FileReader的使用1.txt");

char[] chars = new char[4];
int readCount;
while ((readCount = f1.read(chars)) != -1){
System.out.print(new String(chars,0,readCount));
}
// aasd中文asdok也

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
f1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

FileWriter

只能输出普通文本

public void write(String str) throws IOException

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
import java.io.FileWriter;
import java.io.IOException;

public class _577_FileWriter的使用 {
public static void main(String[] args) {
FileWriter f1 = null;
try {
f1 = new FileWriter("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_577_FileWriter的使用1.txt",true);

String s = "yes中文ok";

f1.write(s);

f1.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (f1 != null){
try {
f1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

使用 FileReader 和 FileWriter 拷贝普通文本文件

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
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class _578_复制普通文本文件 {
public static void main(String[] args) {
FileReader fin = null;
FileWriter fout = null;
try {
fin = new FileReader("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_578_复制普通文本文件1.txt");
fout = new FileWriter("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_578_复制普通文本文件2.txt",true);

char[] chars = new char[1024 * 1024];
int readCount;
while ((readCount = fin.read(chars)) != -1){
fout.write(chars,0,readCount);
}

fout.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fin != null){
try {
fin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fout != null){
try {
fout.close();
} catch (IOException e) {
e.printStackTrace();
}

}
}

}
}

缓冲流

BufferedReader

  1. BufferedReader: 带有缓冲区的字符输入流。使用这个流的时候不需要自定义char数组,或者说不需要自定义byte数组。自带缓冲。
  2. 当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做∶节点流。
  3. 外部负责包装的这个流,叫做:包装流,还有一个名字叫做:处理流。

public String readLine() throws IOException

读一行,不带最后的换行符

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
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class _579_带缓冲区的字符流 {
public static void main(String[] args) throws IOException {
// 当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做∶节点流。
// 外部负责包装的这个流,叫做:包装流,还有一个名字叫做:处理流。
// 当前这个程序来说:FileReader就是一个节点流。BufferedReader就是包装流/处理流。

FileReader reader = new FileReader("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_579_带缓冲区的字符流1.txt");
BufferedReader br = new BufferedReader(reader);

String s = null;
while((s = br.readLine()) != null){
System.out.println(s);
}
/*
123nn
中文
asd
*/



br.close(); // 这里close()时也关闭了reader
}
}

BufferedWriter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.io.BufferedWriter;
import java.io.FileWriter;

public class _581_带有缓冲区的字符输出流 {
public static void main(String[] args) throws Exception{
BufferedWriter f1 = new BufferedWriter(new FileWriter("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_581_带有缓冲区的字符输出流.txt"));
f1.write("hello world!");
f1.write("\n");
f1.write("hello yyy");

f1.flush();

f1.close();
}
}

转换流(将字节流转换成字符流)

InputStreamReader

转换流

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
import java.io.*;

public class _580_节点流和包装流 {
public static void main(String[] args) throws IOException {
FileInputStream f1 = new FileInputStream("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_580_节点流和包装流.txt");

// BufferedReader() 构造方法不能直接放入字节流f1
// 通过转换流 InputStreamReader 的方式转换
InputStreamReader f2 = new InputStreamReader(f1);
BufferedReader f3 = new BufferedReader(f2);

String s = null;
while((s = f3.readLine()) != null){
System.out.println(s);
}
/*
ad
qwe

asd
zx
中午呢
as

*/

}
}


OutputStreamWriter

转换流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStreamWriter;

public class _581_带有缓冲区的字符输出流 {
public static void main(String[] args) throws Exception{
// BufferedWriter f1 = new BufferedWriter(new FileWriter("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_581_带有缓冲区的字符输出流.txt"));
FileOutputStream f1 = new FileOutputStream("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_581_带有缓冲区的字符输出流.txt");
OutputStreamWriter f2 = new OutputStreamWriter(f1);
BufferedWriter f3 = new BufferedWriter(f2);

f3.write("hello world!");
f3.write("\n");
f3.write("hello yyy");

f3.flush();

f3.close();
}
}

数据流

DataOutputStream

java.io.DataOutputStream: 数据专属的流。这个流可以将数据连同数据的类型一并写入文件。
注意:这个文件不是普通文本文档。(这个文件使用记事本打不开。)
写入时将数据和数据类型一并写入

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
import java.io.*;

public class _582_数据流 {
public static void main(String[] args) throws Exception {
DataOutputStream f1 = new DataOutputStream(new FileOutputStream("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_582_数据流1"));
byte b = 100;
short s = 200;
int i = 300;
long l = 400;
float f = 3.0f;
double d = 3.14;
boolean bl = false;
char c = 'a';

f1.writeByte(b);
f1.writeShort(s);
f1.writeInt(i);
f1.writeLong(l);
f1.writeFloat(f);
f1.writeDouble(d);
f1.writeBoolean(bl);
f1.writeChar(c);

f1.flush();
f1.close();
}
}

DataInputStream

DataInputStream:数据字节输入流。
DataOutputStream写的文件,只能使用DataInputStream去读。并且读的时候你需要提前知道写入的顺序。读的顺序需要和写的顺序一致。才可以正常取出数据。

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
import java.io.*;

public class _582_数据流 {
public static void main(String[] args) throws Exception {
DataOutputStream f1 = new DataOutputStream(new FileOutputStream("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_582_数据流1"));
byte b = 100;
short s = 200;
int i = 300;
long l = 400;
float f = 3.0f;
double d = 3.14;
boolean bl = false;
char c = 'a';

f1.writeByte(b);
f1.writeShort(s);
f1.writeInt(i);
f1.writeLong(l);
f1.writeFloat(f);
f1.writeDouble(d);
f1.writeBoolean(bl);
f1.writeChar(c);

f1.flush();
f1.close();

// 怎么写入 怎么读
DataInputStream f2 = new DataInputStream(new FileInputStream("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_582_数据流1"));
byte b2 = f2.readByte();
short s2 = f2.readShort();
int i2 = f2.readInt();
long l2 = f2.readLong();
float ff = f2.readFloat();
double d2 = f2.readDouble();
boolean bl2 = f2.readBoolean();
char c2 = f2.readChar();

System.out.println(b2);
System.out.println(s2);
System.out.println(i2);
System.out.println(l2);
System.out.println(ff);
System.out.println(d2);
System.out.println(bl2);
System.out.println(c2);
/*
100
200
300
400
3.0
3.14
false
a
*/

f2.close();
}
}

标准输出流

标准输出流不需要关闭

PrintStream

public static void setOut(PrintStream out)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;

public class _583_标准输出流 {
public static void main(String[] args) throws FileNotFoundException {
PrintStream ps = System.out;
ps.println(100);
ps.println("aaa");

// 标准输出流不再指向控制台,指向文件
PrintStream f1 = new PrintStream(new FileOutputStream("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_583_标准输出流.txt"));
System.setOut(f1);
//
System.out.println("123");
System.out.println("234");

}
}


File类

  1. FiLe类和四大家族没有关系,所以File类不能完成文件的读和写。
  2. File对象代表什么?
    文件和目录路径名的抽象表示形式。
    C:\Drivers这是一个File对象
    C :\Drivers\Lan\Realtek\Readme.txt也是File对象。

public boolean exists()

1
2
3
4
5
6
7
8
9
10
11
import java.io.File;
import java.io.IOException;

public class _584_File类的理解 {
public static void main(String[] args) throws IOException {
File f1 = new File("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_584_File类的理解");

System.out.println(f1.exists());
}
}

public boolean createNewFile() throws IOException

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.io.File;
import java.io.IOException;

public class _584_File类的理解 {
public static void main(String[] args) throws IOException {
File f1 = new File("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_584_File类的理解");

System.out.println(f1.exists());

if(!f1.exists()){ // 不存在 以文件的形式创建
f1.createNewFile();
}
}
}

public boolean mkdir()

1
2
3
4
5
6
7
8
9
10
11
12
13
import java.io.File;
import java.io.IOException;

public class _584_File类的理解 {
public static void main(String[] args) throws IOException {
File f1 = new File("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_584_File类的理解");

if(!f1.exists()){ // 不存在 以目录的形式创建
f1.mkdir();
}
}
}

public boolean mkdirs()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.io.File;
import java.io.IOException;

public class _584_File类的理解 {
public static void main(String[] args) throws IOException {
File f1 = new File("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_584_File类的理解");

File f2 = new File("D:a/b/c/d/e");
if(!f2.exists()){ // 不存在 以多重目录新建
f2.mkdirs();
}

}
}

public String getParent()

1
2
3
4
5
6
7
8
9
10
11
12
13
import java.io.File;
import java.io.IOException;

public class _584_File类的理解 {
public static void main(String[] args) throws IOException {
File f3 = new File("D:\\cc\\bb\\aa.txt");
// 获取父路径
String f3parent = f3.getParent();
System.out.println(f3parent);

}
}

public File getParentFile()

1
2
3
4
5
6
7
8
9
10
11
12
13
import java.io.File;
import java.io.IOException;

public class _584_File类的理解 {
public static void main(String[] args) throws IOException {
File f3 = new File("D:\\cc\\bb\\aa.txt");
// 获取父文件 以及 绝对路径
File parentFile = f3.getParentFile();
System.out.println(parentFile.getAbsolutePath());

}
}

public String getAbsolutePath()

1
2
3
4
5
6
7
8
9
10
11
12
import java.io.File;
import java.io.IOException;

public class _584_File类的理解 {
public static void main(String[] args) throws IOException {
File f3 = new File("D:\\cc\\bb\\aa.txt");
// 获取父文件 以及 绝对路径
File parentFile = f3.getParentFile();
System.out.println(parentFile.getAbsolutePath());

}
}

public String getName()

1
2
3
4
5
6
7
8
9
10
11
12
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

public class _585_File类的常用方法 {
public static void main(String[] args) {
File f1 = new File("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_585_File类的常用方法.java");
// 获取文件名
System.out.println(f1.getName());
}
}

public boolean isDirectory()

1
2
3
4
5
6
7
8
9
10
11
12
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

public class _585_File类的常用方法 {
public static void main(String[] args) {
File f1 = new File("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_585_File类的常用方法.java");
// 判断是否是目录
System.out.println(f1.isDirectory());
}
}

public boolean isFile()

1
2
3
4
5
6
7
8
9
10
11
12
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

public class _585_File类的常用方法 {
public static void main(String[] args) {
File f1 = new File("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_585_File类的常用方法.java");
// 判断是否是文件
System.out.println(f1.isFile());
}
}

public long lastModified()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

public class _585_File类的常用方法 {
public static void main(String[] args) {
File f1 = new File("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_585_File类的常用方法.java");
// 获取文件最后一次修改时间
long l = f1.lastModified(); // 返回 1970 年到现在的总毫秒数
// 转化毫秒
Date date = new Date(l);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
System.out.println(sdf.format(date));
}
}

public long length()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

public class _585_File类的常用方法 {
public static void main(String[] args) {
File f1 = new File("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_585_File类的常用方法.java");
// 获取文件大小
System.out.println(f1.length()); // 单位字节



}
}

public File[] listFiles()

1
2
3
4
5
6
7
8
9
10
11
12
13
import java.io.File;

public class _586_File类的常用方法 {
public static void main(String[] args) {
File f1 = new File("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src");
// 获取该文件下子目录
File[] files = f1.listFiles();
for (File f : files){
System.out.println(f.getAbsolutePath());
}
}
}

目录拷贝

为了方便 异常都抛出了…
前提得保证 G 盘下有 src文件或目录 和 dst 目录

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
import java.io.*;

public class _588_目录拷贝 {

public static void copy(File fin, File fout) throws IOException {
if(fin.isFile()){ // 是文件
String name = fin.getName();
String dstPath = fout.getAbsolutePath() + "\\" + name;
// 开始copy文件
FileInputStream src = new FileInputStream(fin.getAbsolutePath());
FileOutputStream dst = new FileOutputStream(dstPath);
byte[] bytes = new byte[1024 * 1024];
int readCount = 0;
while ((readCount = src.read(bytes)) != -1){
dst.write(bytes, 0, readCount);
}
dst.flush();
dst.close();
src.close();
return;
}
else if (fin.isDirectory()){ // 是目录
String name = fin.getName();
String dstPath = fout.getAbsolutePath() + "\\" + name;
File file = new File(dstPath);
file.mkdir();
File[] files = fin.listFiles();
for (File f : files){
copy(new File(f.getAbsolutePath()), new File(dstPath));
}
}
}

public static void main(String[] args) throws Exception{
// 前提得保证 G 盘下有 src文件或目录 和 dst 目录
File fin = new File("G:\\src");
File fout = new File("G:\\dst");
copy(fin, fout);
System.out.println("copy ok~");
System.out.println("将 src 目录以及目录下的文件放入了 dst 目录下");
System.out.println("也就是 G:\\dst\\src\\...");
}
}

序列化和反序列化

序列化和反序列化的理解

这儿应该有张图…

序列化的实现(ObjectOutputStream)

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
import java.io.*;

public class _591_序列化的实现 {
public static void main(String[] args) throws IOException {
Student s = new Student("张三", 111);

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_591_序列化的实现.txt"));

oos.writeObject(s);

oos.flush();
oos.close();

}
}

class Student implements Serializable { // 必须实现 Serializable可序列化 接口
private String name;
private int id;

public Student() {
}

public Student(String name, int id) {
this.name = name;
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", id=" + id +
'}';
}
}


Serializable接口

  1. public interface Serializable {}
    这个接口当中什么代码都没有。
    它起到标识的作用,Serializable这个标志接口是给java虚拟机参考的,java虚拟机看到这个接口之后,会为该类自动生成一个序列化版本号。
  2. java区分类首先靠名字,名字一样靠序列化版本号
  3. java自动生成的序列化版本号缺点是:一旦代码确定之后,不能进行后续的修改,因为只要修改,必然会重新编译,此时会生成全新的序列化版本号,这个时候java虚拟机会认为这是一个全新的类。(这样就不好了! )
  4. Java虚拟机看到erializable接口之后,会自动生成―个序列化版本号。
    这里没有手动写出来,java虚拟机会默认提供这个序列化版本号。
    建议将序列化版本号手动的写出来。不建议自动生成
    1
    private static final long serialVersionuID = 4564565434565434L;

反序列化的实现(ObjectInputStream)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class _592_反序列化的实现 {
public static void main(String[] args) throws Exception{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_591_序列化的实现.txt"));
// 开始反序列化
Object o = ois.readObject();
System.out.println(o);
// 关闭
ois.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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import java.io.*;
import java.util.ArrayList;

public class _593_序列化多个对象 {
public static void main(String[] args) throws Exception{
// 序列化
ArrayList<User> list = new ArrayList<>();
list.add(new User(100,"zhangsan"));
list.add(new User(200,"lisi"));
list.add(new User(300,"wangwu"));

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_593_序列化多个对象.txt"));
oos.writeObject(list);

oos.flush();
oos.close();

// 反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_593_序列化多个对象.txt"));
ArrayList<User> list2 = (ArrayList<User>)ois.readObject();
for (User u : list2){
System.out.println(u);
}
/*
User{ID=100, name='zhangsan'}
User{ID=200, name='lisi'}
User{ID=300, name='wangwu'}
*/

ois.close();
}
}

class User implements Serializable {
int ID;
String name;

public User(int ID, String name) {
this.ID = ID;
this.name = name;
}

@Override
public String toString() {
return "User{" +
"ID=" + ID +
", name='" + name + '\'' +
'}';
}
}

transient关键字

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
import java.io.*;
import java.util.ArrayList;

public class _594_transient关键字 {
public static void main(String[] args) throws Exception{
// 序列化
ArrayList<User2> list = new ArrayList<>();
list.add(new User2(100,"zhangsan"));
list.add(new User2(200,"lisi"));
list.add(new User2(300,"wangwu"));

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_594_transient关键字.txt"));
oos.writeObject(list);

oos.flush();
oos.close();

// 反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_594_transient关键字.txt"));
ArrayList<User2> list2 = (ArrayList<User2>)ois.readObject();
for (User2 u : list2){
System.out.println(u);
}
/*
User2{ID=0, name='zhangsan'}
User2{ID=0, name='lisi'}
User2{ID=0, name='wangwu'}
*/

ois.close();
}
}

class User2 implements Serializable {
transient int ID; // transient 表示游离的 不参与序列化过程
String name;

public User2(int ID, String name) {
this.ID = ID;
this.name = name;
}

@Override
public String toString() {
return "User2{" +
"ID=" + ID +
", name='" + name + '\'' +
'}';
}
}

IO和Properties的联合使用

以后经常改变的数据,可以单独写到一个文件中,使用程序动态读取。将来只需要修改这个文件的内容,java代码不需要改动,不需要重新编译,服务器也不需要重启。就可以拿到动态的信息。
类似于以上机制的这种文件被称为配置文件。
并且当配置文件中的内容格式是:
key1=vaLue
key2=value
的时候,我们把这种配置文件叫做属性配置文件。
java规范中有要求:属性配置文件建议以.properties结尾,但这不是必须的。

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
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;

public class _597_IOProperties的联合使用 {
public static void main(String[] args) throws IOException {
/* 文件中的内容
username=admin
password=123456
*/
FileInputStream f1 = new FileInputStream("D:\\Workspace\\Java\\【JavaSE】BiliBili动力节点\\【561-597】IO流\\src\\_597_IO和Properties的联合使用.txt");
Properties mp = new Properties();
mp.load(f1);

System.out.println(mp.getProperty("username")); // admin
System.out.println(mp.getProperty("password")); // 123456

// 遍历 key 和 val
Set<Object> objects = mp.keySet();
for (Object o : objects){
System.out.println(o + "=" + mp.getProperty(o.toString()));
}
/*
password=123456
username=admin
*/
}
}

Prev
2022-02-01 18:40:00 # JavaSE
Next