# IO编程
Java提供了java.io工具包来处理,其核心类有File,InputStream,OutputStream,Reader,Writer,Serializable。它们的关联如下:
# File类基本操作
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
class MyFileOper {
File file;
public boolean createFile(String filePath, boolean isDeleteCurrent) throws IOException {
file = new File(filePath);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
if (isDeleteCurrent && file.exists()) {
file.delete();
System.out.println("删除已有文件!");
}
return file.createNewFile();
}
public static void GetCurrentWorkFolder() {
// 获取当前目录
File currentDirectory = new File("");// 设定为当前文件夹
try {
System.out.println(currentDirectory.getCanonicalPath());
System.out.println(currentDirectory.getAbsolutePath());// 获取绝对路径
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void GetAttribute() {
System.out.println("文件是否可写:" + file.canWrite());
System.out.println("文件是否可读:" + file.canRead());
System.out
.println("最后修改时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(file.lastModified())));
System.out.println("文件是否为目录:" + file.isDirectory());
}
public static void GetFolderFileList(String filePath) {
File fileOper = new File(filePath);
if (fileOper != null && fileOper.isDirectory()) {
File result[] = fileOper.listFiles();
if (result != null)
for (int i = 0; i < result.length; i++) {
System.out.println(result[i].getAbsolutePath());
GetFolderFileList(result[i].getAbsolutePath());
}
}
}
public void ChangeFileName() {
File newFileName = new File(file.getParentFile(),"NewFileName.md");
file.renameTo(newFileName);
}
}
public class Main {
public static void main(String[] args) throws IOException {
MyFileOper myFileOper = new MyFileOper();
//创建某个文件,File.separator代表了不同系统中的文件分隔符,Windows中路径分隔符为"\",Linux系统中为"/"。
myFileOper.createFile("test" + File.separator + "work" + File.separator + "hello.txt", false);
//获取文件属性
myFileOper.GetAttribute();
//获取文件目录列表
myFileOper.GetFolderFileList("D:\\");
//改变文件名
myFileOper.ChangeFileName();
}
}
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
# 字节流和字符流
在程序中,数据以流的形式传输和保存,想象下家里的自来水管,从水厂中引流到家里,然后使用后进入下水道,可以形象地展示流的概念。在Java中读取数据时利用输入流来完成,输出数据时用输出流,基本上有两类支持:
- 字节操作流,在JDK 1.0定义,有OutputStream和InputStream。
- 字符操作流,在JDK 1.1定义,有Writer和Reader。
操作步骤有:
- 使用文件对象来新建一个File类对象作为文件描述符。
- 通过字节流或字符流子类来实例化相应流。
- 执行读写操作。
- 通过文件描述符关闭资源。
# 字节输入输出流
字节是I/O操作的基本数据单位
- 输出流由抽象类OutputStream来完成,它实现了Closeable和Flushable接口,在JDK1.5之前close()和flush()都是直接定义在OutputStream类中。如果要向文件输出,可使用FileOutputStream子类。
- 输入流由抽象类InputStream来完成,它实现了Closeable接口。如果要从文件读入,可使用FileInputStream子类。
FileOutputStream类继承结构如下:
FileInputStream类继承结构如下:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class Main {
public static void main(String[] args) {
File file = new File("ByteStream.txt");
try {
OutputStream outputFile = new FileOutputStream(file);
outputFile.write("这是一个测试文件!".getBytes());
outputFile.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
InputStream inputFile;
try {
inputFile = new FileInputStream(file);
byte data[] = new byte[1024];
int len=inputFile.read(data);
System.out.println("结果为:"+new String(data,0,len));
inputFile.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
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
它们可使用AutoCloseable自动关闭接口:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class Main {
public static void main(String[] args) {
File file = new File("ByteStream.txt");
try (OutputStream outputFile = new FileOutputStream(file)) {
outputFile.write("这是一个测试文件!".getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try (InputStream inputFile = new FileInputStream(file)) {
byte data[] = new byte[1024];
int len = inputFile.read(data);
System.out.println("结果为:" + new String(data, 0, len));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
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
# 字符输入输出流
Java中底层通信处理都是依靠字节实现数据交互,在程序为了方便进行中文处理,可使用字符数据类型:
- Writer类实现了Appendable,Closeable,Flushable接口。
- Reader类实现了Readable和Closeable接口。
Writer类的继承结构如下:
Reader类的继承结构如下:
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
public class Main {
public static void main(String[] args) {
File file = new File("CharStream.txt");
try (Writer outputFile = new FileWriter(file)) {
outputFile.write("这是一个测试文件!");
outputFile.append("hello!");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try (Reader inputFile = new FileReader(file)) {
char data[] = new char[1024];
int len = inputFile.read(data);
System.out.println("结果为:" + new String(data, 0, len));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
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
# 字节流和字符流区别
它们底层传输的都是字节数据,它们最大的区别是字符流使用了缓冲区,字节流则是直接进行数据处理操作,当使用字符输出流时必须使用Flushable接口提供了flush()方法强制性刷新缓冲区的内容。
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
public class Main {
public static void main(String[] args) {
File file = new File("CharStream.txt");
try (Writer outputFile = new FileWriter(file)) {
outputFile.write("这是一个测试文件!");
outputFile.append("hello!");
outputFile.flush();
try (Reader inputFile = new FileReader(file)) {
char data[] = new char[1024];
int len = inputFile.read(data);
System.out.println("结果为:" + new String(data, 0, len));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
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
注意进行close操作时也会刷新缓冲区。
# 转换流
转换流的目的是解决字节流和字符流之间操作类型的转换,它有两个类:OutputStreamWriter和InputStreamReader。它们分别是Writer和Reader的子类,可传入相应的字节流即可完成将字节流转换为字符流的操作。
OutputStreamWriter类的继承结构如下:
InputStreamReader类的继承结构如下:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
public class Main {
public static void main(String[] args) throws IOException {
File file = new File("CharStream.txt");
OutputStream outputStream = new FileOutputStream(file);
Writer outWriter = new OutputStreamWriter(outputStream);
outWriter.append("呵呵呵呵呵");
outWriter.close();
outputStream.close();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 文件夹复制实例
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
class CopyFolder {
private String targetBaseFolderString;
public boolean CreateFolder=false;
private boolean SetTarget(String targetPath) {
File tempFile = new File(targetPath);
if (tempFile.isDirectory()) {
this.targetBaseFolderString = targetPath;
return true;
} else {
return false;
}
}
public void CopyFolderFileToTarget(String filePath,String targetFolder) {
if(!SetTarget(targetFolder)) {
System.out.println("目标目录 不是目录!");
return;
}
GetFolderFileListAndCopy(new File(filePath), new File(targetFolder));
}
private void GetFolderFileListAndCopy(File sourcePathDes,File targetPathDes) {
if(sourcePathDes.isDirectory() && !targetPathDes.exists() && CreateFolder) {
targetPathDes.mkdir();
System.out.println("创建了目录:"+targetPathDes);
}
if (sourcePathDes != null && sourcePathDes.isDirectory()) {
File result[] = sourcePathDes.listFiles();
if (result != null)
for (int i = 0; i < result.length; i++) {
//System.out.println(result[i].getAbsolutePath());
GetFolderFileListAndCopy(result[i],new File(targetPathDes+File.separator+result[i].getName()));
}
}
if (sourcePathDes.isFile()) {
CopyFileToTarget(sourcePathDes,targetPathDes);
System.out.println(sourcePathDes.getName()+" copied to "+targetPathDes);
}
}
private void CopyFileToTarget(File source, File target) {
if (!target.getParentFile().exists()) {
target.getParentFile().mkdirs();
System.out.println("创建了目标文件目录"+target.getParentFile());
}
InputStream inputStream = null;
OutputStream outputStream = null;
try {
inputStream = new FileInputStream(source);
outputStream = new FileOutputStream(target);
try {
inputStream.transferTo(outputStream);
// int len=0;
// byte data[]=new byte[1000];
// while((len=inputStream.read(data))!=-1) {
// outputStream.write(data,0,len);
// }
inputStream.close();
outputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Main {
public static void main(String[] args) {
CopyFolder cp1 = new CopyFolder();
cp1.CreateFolder=true;
cp1.CopyFolderFileToTarget("D:\\temp\\cn","D:\\temp\\target");
}
}
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
77
78
79
80
81
82
83
84
85
86
87
88
如果上面的CreateFolder设置为True,会创建原目录中的空目录,否则只创建原目录中有文件的目录。JDK 1.9之后才提供transferTo()方法,在JDK 1.9之前否则需要上面注释部分。
# 字符编码
计算机中所有语言显示的文字都是有编码的,一个编码对应相应图形,在显示器上是图形,在内存里是编码数字。下面是常用的编码:
- ISO8859-1:国际通用单字节编码,0-255的范围,主要用于英文,向下兼容ASCII码。
- GBK/GB2312:中文的国际编码,双字节编码,GBK可表示简体和繁体中文,GB2312只能表示简体中文,GBK兼容GB2312。
- UNICODE:可以准确表示任何语言文字,不兼容ISO8859-1。
- UTF-8编码:是UNICODE的编码方式,兼容ISO8859-1,不定长编码。
从JDK 1.9开始,Java的默认编码是UTF-8。
# 乱码问题
有些文件在系统中打开会是乱码,可能是因为文件自身的编码不是系统的默认编码,比如系统默认是GBK,但在写文件时用的是UTF-8,这就好比一个英国人用英语跟日本人说话,一个不熟悉英语的日本人根本就听不懂。
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Main {
public static void main(String[] args) {
System.out.println("系统编码:"+System.getProperty("file.encoding"));
//写文件时指定编码
try {
OutputStream outputStream = new FileOutputStream("test.txt");
try {
outputStream.write("世界和平".getBytes("GB2312"));
outputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 内存操作流
它以内存作为操作对象实现的IO数据处理,前面的操作对象都是文件,内存操作流不会进行磁盘数据操作。Java中提供以下两类操作流:
- 字节内存操作流:ByteArrayOutputStream,ByteArrayInputStream。
- 字符内存操作流:CharArrayWriter,CharArrayReader。
字节的类继承结构如下:
字符的类继承结构如下:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class Main {
public static void main(String[] args) {
String strOrg = "hello world!";
InputStream inputStream = new ByteArrayInputStream(strOrg.getBytes());
OutputStream outputStream = new ByteArrayOutputStream();
int data = 0;
byte result[] = null;
try {
while ((data = inputStream.read()) != -1) {
outputStream.write(Character.toUpperCase(data));
}
System.out.println(outputStream);
//将全部数据转为字节取出。
result = ((ByteArrayOutputStream) outputStream).toByteArray();
inputStream.close();
outputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(new String(result));
}
}
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
# 管道流
管道流主要用在两个线程间通信,分为管道输出流(PipedOutputStream,PipedWriter)和管道输入流(PipedInputStream,PipedReader)。
字节管道流的继承结构如下:
字符管道流的继承结构如下:
要想进行管道输出,则必须把输出流连在输入流上。有下面两个方法:
- PipedOutputStream类中的connect(PipedInputStream snk)方法。
- PipedWriter类中的connect(PipedReader snk)方法。
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
class SendDataThread implements Runnable{
private PipedOutputStream output;
public SendDataThread() {
// TODO Auto-generated constructor stub
this.output = new PipedOutputStream();
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
this.output.write("hello world,this is sended by send data thread".getBytes());
this.output.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public PipedOutputStream getOutput() {
return output;
}
}
class ReceiveDataThread implements Runnable{
private PipedInputStream input;
public ReceiveDataThread() {
this.input=new PipedInputStream();
}
@Override
public void run() {
// TODO Auto-generated method stub
byte data[]=new byte[1024];
int len=0;
ByteArrayOutputStream bOutputStream = new ByteArrayOutputStream();
try {
while((len=this.input.read(data))!=-1) {
bOutputStream.write(data,0,len);
}
System.out.println(new String(bOutputStream.toByteArray()));
bOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
this.input.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public PipedInputStream getInput() {
return input;
}
}
public class Main {
public static void main(String[] args) {
SendDataThread send = new SendDataThread();
ReceiveDataThread receive = new ReceiveDataThread();
try {
send.getOutput().connect(receive.getInput());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new Thread(send,"消息发送线程").start();
new Thread(receive,"消息接收线程").start();
}
}
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
77
78
79
80
81
82
# RandomAccessFile
可实现文件数据的随机读取,通过对文件指针位置的设置,实现部分数据的读取。
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
public class Main {
static RandomAccessFile randomFile;
public static void main(String[] args) throws IOException {
File file = new File("test.txt");
randomFile = new RandomAccessFile(file, "rw");
String name[] = new String[] {"zhang","wang","li"};
int score[] = new int[] {18,20,22};
for(int i=0;i<name.length;i++) {
randomFile.write(name[i].getBytes());
randomFile.writeInt(score[i]);
}
randomFile.seek(0);
GetInfo(5);
randomFile.seek(9);
GetInfo(4);
randomFile.seek(17);
GetInfo(2);
randomFile.close();
}
public static byte[] GetInfo(int nameLength) {
byte[] data = new byte[nameLength];
try {
int len = randomFile.read(data);
System.out.println("名字:"+new String(data,0,len).trim()+" 年龄:"+randomFile.readInt());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return data;
}
}
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
# 打印流
java.io包中对于数据的输出可通过OutputStream或Writer类完成,但是OutputStream只允许输出字节数据,Writer只允许输出字符数据和字符串数据,但是在实际打印中需要多种数据类型的数据,比如整数,浮点数,字符,引用参数,为了简化输出操作,提供了两个打印流操作类:
- 字节打印流(PrintStream)
- 字符打印流(PrintWriter)
它的类继承结构如下:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
public class Main {
public static void main(String[] args) {
File file = new File("test.txt");
PrintWriter printWriter;
try {
printWriter = new PrintWriter(new FileOutputStream(file));
printWriter.println("this is title:");
printWriter.println("info:hello");
String nameString = "xie";
int age = 22;
double score = 89.887;
printWriter.printf("name:%s,age:%d,money:%5.2f", nameString, age, score);
printWriter.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# System的IO
System中有三个和IO操作的常量,它们的声明如下:
public static final PrintStream err;
public static final PrintStream out;
public static final InputStream in;
2
3
实例如下:
import java.io.IOException;
import java.io.InputStream;
public class Main {
public static void main(String[] args) {
System.out.println("测试err和in:");
System.err.println("这是一个错误!");
InputStream inputStream = System.in;
byte[] data = new byte[5];
try {
int len = inputStream.read(data);
System.out.println("数据为:"+new String(data,0,len));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
注意上面的System.in对中文的处理支持不够好。
# BufferedReader缓冲输入流
它提供一种字符流的缓冲区数据读取,它读取数据时会把数据暂时放到缓冲区,利用其它方法将读取的内容一次性取出。它的类继承结构如下:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) {
BufferedReader inputBufferedReader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("输入年龄:");
try {
String msg = inputBufferedReader.readLine();
if(msg.matches("\\d{1,3}")) {
System.out.print("年龄为:"+Integer.parseInt(msg));
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Scanner输入流
Scanner支持各种输入数据类型的转换,开发者可以利用其提供的方法判断输入的数据类型,也可以获取指定类型的数据。它的类继承结构如下:
判断是否为整形:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("输入年龄:");
if(scanner.hasNextInt()) {
System.out.println("年龄为:"+scanner.nextInt());
}else {
System.out.println("输入的内容不是数字!");
}
scanner.close();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
判断输入是否为要求的日期格式:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("输入日期:");
if(scanner.hasNext("\\d{4}-\\d{2}-\\d{2}")) {
String str = scanner.next("\\d{4}-\\d{2}-\\d{2}");
try {
System.out.println("输入信息为:"+new SimpleDateFormat("yyy-MM-dd").parse(str));
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else {
System.out.println("输入的内容不符合要求!");
}
scanner.close();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
读取文件内容:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws FileNotFoundException {
Scanner scanner = new Scanner(new File("test.txt"));
scanner.useDelimiter("\n");
while(scanner.hasNext()) {
System.out.print(scanner.next());
}
scanner.close();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
Scanner默认把空字符作为分隔符。
# 对象序列化
对象序列化是把一个对象变为二进制的数据流的一种方法,这样可以方便地实现对象的传输和存储。一个类如果想被序列化,所在的类必须实现java.io.Serializable接口,此接口并没提供任何抽象方法,只是一个标识接口,标识对象可被序列化。
Serializable接口只是标识了一个类对象能否被允许序列化,对于对象序列化和反序列化的具体实现需要依靠ObjectOutputStream与ObjectInputStream两类完成。ObjectInputStream可以读取ObjectOutputStream类输出的二进制对象数据,并转为具体类型的对象并返回。相关类的关系如下:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class MyInfo implements Serializable{
String keyString;
transient String infoString;
public MyInfo(String key,String info){
keyString = key;
infoString = info;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "key:"+keyString+";"+"info:"+infoString;
}
}
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
File saveFile = new File("test.txt");
MyInfo myInfo = new MyInfo("name", "xie");
try {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(saveFile));
oos.writeObject(myInfo);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(saveFile));
Object obj = ois.readObject();
ois.close();
System.out.println(obj);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
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
注意在对象进行序列化与反序列化的时候要考虑JDK版本的问题,如果序列化的JDK和反序列化的JDK版本不统一则很有可能造成异常,序列化的时候引入了一个serialVersionUID常量,通过它来判断版本的一致性,反序列化时会判断该值与本地的serialVersionUID是否相同,如果相同就一致。
在实现java.io.Serializable接口的实体类并没有定义一个serialVersionUID,Java虚拟机在编译时自动生成一个该变量,如果希望自己控制可以自己来定义一个这样的变量。
默认情况下,执行对象序列化的时候会将类中的全部属性的内容进行序列化操作,当有一些属性并不需要序列化的时候,可以在属性定义上使用transient关键字来定义。