概念:代表物理盘符中的⼀个⽂件或者⽂件夹。
常见方法:
方法名 |
描述 |
createNewFile() |
创建⼀个新文件。 |
mkdir() |
创建⼀个新⽬录。 |
delete() |
删除⽂件或空⽬录。 |
exists() |
判断File对象所对象所代表的对象是否存在。 |
getAbsolutePath() |
获取⽂件的绝对路径。 |
getName() |
取得名字。 |
getParent() |
获取⽂件/⽬录所在的⽬录。 |
isDirectory() |
是否是⽬录。 |
isFile() |
是否是⽂件。 |
length() |
获得⽂件的⻓度。 |
listFiles() |
列出⽬录中的所有内容 |
示例:
//⽂件的相关操作
File f = new File("d:/aaa/bbb.java");
System.out.println("⽂件绝对路径:"+f.getAbsolutePath());
System.out.println("⽂件构造路径:"+f.getPath());
System.out.println("⽂件名称:"+f.getName());
System.out.println("⽂件⻓度:"+f.length()+"字节");
//创建⽂件 createNewFile()
File file=new File("d:\\file.txt");
//System.out.println(file.toString());
if(!file.exists()) {
boolean b=file.createNewFile();
System.out.println("创建结果:"+b);
}
System.out.println("是否时⽂件:"+file.isFile());
//⽂件夹的相关操作
File f2 = new File("d:/aaa");
System.out.println("⽬录绝对路径:"+f2.getAbsolutePath());
System.out.println("⽬录构造路径:"+f2.getPath());
System.out.println("⽬录名称:"+f2.getName());
System.out.println("⽬录⻓度:"+f2.length());
//遍历⽂件夹
File dir2=new File("d:\\图⽚");
String[] files=dir2.list();
System.out.println("--------------------------------");
for (String string : files) {
System.out.println(string);
}
FileFilter:⽂件过滤器接⼝
boolean accept(File pathname)。
当调⽤File类中的listFiles()⽅法时,⽀持传⼊FileFilter接⼝接⼝实现类,对获取⽂件进⾏过滤,只有满足条件的⽂件的才可出现在listFiles()的返回值中。
示例:
public class DiGuiDemo {
public static void main(String[] args) {
File f = new File("d:\\QF\\test");
printDir(dir);
}
public static void printDir(File dir) {
// 匿名内部类⽅式,创建过滤器⼦类对象
File[] files = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().endsWith(".java")||pathname.isDirectory();
}
});
// 循环打印
for (File file : files) {
if (file.isFile()) {
System.out.println("⽂件名:" + file.getAbsolutePath());
} else {
printDir2(file);
}
}
}
}
⽣活中,你肯定经历过这样的场景。当你编辑⼀个⽂本⽂件,忘记了ctrl+s ,可能⽂件就⽩⽩编辑了。当你电脑上插⼊⼀个U盘,可以把⼀个视频,拷⻉到你的电脑硬盘⾥。那么数据都是在哪些设备上的呢?键盘、内存、硬盘、外接设备等等。
我们把这种数据的传输,可以看做是⼀种数据的流动,按照流动的⽅向,以内存为基准,分为输⼊input 和输出output ,即流向内存是输⼊流,流出内存的输出流。
Java中I/O操作主要是指使⽤java.io包下的内容,进⾏输⼊、输出操作。输⼊也叫做读取数据,输出也叫做作写出数据。
按照流的流向分,可以分为输入流和输出流;
按照操作单元划分,可以划分为字节流和字符流;
按照流的角色划分为节点流和处理流。
Java Io流共涉及40多个类,这些类看上去很杂乱,但实际上很有规则,而且彼此之间存在非常紧密的联系,
Java I0流的40多个类都是从如下4个抽象类基类中派生出来的。
InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。
⼀切⽂件数据(⽂本、图⽚、视频等)在存储时,都是以⼆进制数字的形式保存,都⼀个⼀个的字节,那么传输时⼀样如此。所以,字节流可以传输任意⽂件数据。在操作流的时候,我们要时刻明确,⽆论使⽤什么样的流对象,底层传输的始终为⼆进制数据。
java.io.OutputStream抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到⽬的地。它定义了字节输出流的基本共性功能⽅法。
public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。
public void write(byte[] b):将 b.length字节从指定的字节数组写⼊此输出流。
public void write(byte[] b, int off, int len) :从指定的字节数组写⼊ len字节,从偏移量 off开始输出到此输出流。
public abstract void write(int b) :将指定的字节输出流。
构造⽅法:
public FileOutputStream(File file):创建⽂件输出流以写⼊由指定的 File对象表示的⽂件。
public FileOutputStream(String name): 创建⽂件输出流以指定的名称写⼊⽂件。
1、写出字节:write(int b) ⽅法,每次可以写出⼀个字节数据
2、写出字节数组:write(byte[] b),每次可以写出数组中的数据
3、写出指定⻓度字节数组:write(byte[] b, int off, int len) ,每次写出从off索引开始,len个字节
示例:
// 使⽤File对象创建流对象
File file = new File("a.txt");
FileOutputStream fos = new FileOutputStream(file);
// 使⽤⽂件名称创建流对象
FileOutputStream fos = new FileOutputStream("b.txt");
// 使⽤⽂件名称创建流对象
FileOutputStream fos = new FileOutputStream("fos.txt");
// 写出数据:虽然参数为int类型四个字节,但是只会保留⼀个字节的信息写出
fos.write(97); // 写出第1个字节
fos.write(98); // 写出第2个字节
fos.write(99); // 写出第3个字节
// 关闭资源
fos.close();
// 使⽤⽂件名称创建流对象
FileOutputStream fos = new FileOutputStream("fos.txt");
// 字符串转换为字节数组
byte[] b = "你好中国".getBytes();
// 写出字节数组数据
fos.write(b);
// 关闭资源
fos.close();
// 使⽤⽂件名称创建流对象
FileOutputStream fos = new FileOutputStream("fos.txt");
// 字符串转换为字节数组
byte[] b = "abcde".getBytes();
// 写出从索引2开始,2个字节。索引2是c,两个字节,也就是cd。
fos.write(b,2,2);
// 关闭资源
fos.close();
java.io.InputStream抽象类是表示字节输⼊流的所有类的超类,可以读取字节信息到内存中。它定义了字节输⼊流的基本共性功能⽅法。
public void close() :关闭此输⼊流并释放与此流相关联的任何系统资源。
public abstract int read(): 从输⼊流读取数据的下⼀个字节。
public int read(byte[] b): 从输⼊流中读取⼀些字节数,并将它们存储到字节数组 b中 。
构造⽅法:
FileInputStream(File file): 通过打开与实际⽂件的连接来创建⼀个 FileInputStream ,该⽂件
由⽂件系统中的 File对象 file命名。
FileInputStream(String name): 通过打开与实际⽂件的连接来创建⼀个 FileInputStream ,该
⽂件由⽂件系统中的路径名 name命名。
1、读取字节:read⽅法,每次可以读取⼀个字节的数据,提升为int类型,读取到⽂件末尾,返回-1
2、使⽤字节数组读取:read(byte[] b),每次读取b的⻓度个字节到数组中,返回读取到的有效字节个数,读取到末尾时,返回-1
示例:
// 使⽤File对象创建流对象
File file = new File("a.txt");
FileInputStream fos = new FileInputStream(file);
// 使⽤⽂件名称创建流对象
FileInputStream fos = new FileInputStream("b.txt");
// 使⽤⽂件名称创建流对象
FileInputStream fis = new FileInputStream("read.txt");
// 读取数据,返回⼀个字节
int read = fis.read();
System.out.println((char) read);
read = fis.read();
System.out.println((char) read);
read = fis.read();
System.out.println((char) read);
read = fis.read();
System.out.println((char) read);
read = fis.read();
System.out.println((char) read);
// 读取到末尾,返回-1
read = fis.read();
System.out.println( read);
// 关闭资源
fis.close();
// 使⽤⽂件名称创建流对象
FileInputStream fis = new FileInputStream("read.txt");
// 定义变量,保存数据
int b ;
// 循环读取
while ((b = fis.read())!=-1) {
System.out.println((char)b);
}
// 关闭资源
fis.close();
// 使⽤⽂件名称创建流对象.
FileInputStream fis = new FileInputStream("read.txt"); // ⽂件中为abcde
// 定义变量,作为有效个数
int len ;
// 定义字节数组,作为装字节数据的容器
byte[] b = new byte[2];
// 循环读取
while (( len= fis.read(b))!=-1) {
// 每次读取后,把数组的有效字节部分,变成字符串打印
System.out.println(new String(b,0,len));// len 每次读取的有效字节个数
}
// 关闭资源
fis.close();
//1创建流
//1.1⽂件字节输⼊流
FileInputStream fis=new FileInputStream("d:\\001.jpg");
//1.2⽂件字节输出流
FileOutputStream fos=new FileOutputStream("d:\\002.jpg");
//2⼀边读,⼀边写
byte[] buf=new byte[1024];
int count=0;
while((count=fis.read(buf))!=-1) {
fos.write(buf,0,count);
}
//3关闭
fis.close();
fos.close();
System.out.println("复制完毕");
java.io.Reader 抽象类是表示⽤于读取字符流的所有类的超类,可以读取字符信息到内存中。它定义了字符输⼊流的基本共性功能⽅法。
public void close() :关闭此流并释放与此流相关联的任何系统资源。
public int read() : 从输⼊流读取⼀个字符。
public int read(char[] cbuf) : 从输⼊流中读取⼀些字符,并将它们存储到字符数组cbuf中 。
构造方法
FileReader(File file) : 创建⼀个新的 FileReader ,给定要读取的File对象。
FileReader(String fileName) : 创建⼀个新的 FileReader ,给定要读取的⽂件的名称。
构造时使⽤系统默认的字符编码和默认字节缓冲区。
1. 字符编码:字节与字符的对应规则。Windows系统的中⽂编码默认是GBK编码表。idea中UTF-8
2. 字节缓冲区:⼀个字节数组,⽤来临时存储字节数据。
示例:
// 使⽤File对象创建流对象
File file = new File("a.txt");
FileReader fr = new FileReader(file);
// 使⽤⽂件名称创建流对象
FileReader fr = new FileReader("b.txt");
// 使⽤⽂件名称创建流对象
FileReader fr = new FileReader("read.txt");
// 定义变量,保存有效字符个数
int len ;
// 定义字符数组,作为装字符数据的容器
char[] cbuf = new char[2];
// 循环读取
while ((len = fr.read(cbuf))!=-1) {
System.out.println(new String(cbuf,0,len));
}
// 关闭资源
fr.close();
java.io.Writer 抽象类是表示⽤于写出字符流的所有类的超类,将指定的字符信息写出到⽬的地。
它定义了字符输出流的基本共性功能⽅法。
void write(int c) 写⼊单个字符。
void write(char[] cbuf) 写⼊字符数组。
abstract void write(char[] cbuf, int off, int len) 写⼊字符数组的某⼀部分,off数组的开始索引,len写的字符个数。
void write(String str) 写⼊字符串。
void write(String str, int off, int len) 写⼊字符串的某⼀部分,off字符串的开始索引,len写的字符个数。
void flush() 刷新该流的缓冲。
void close() 关闭此流,但要先刷新它。
FileWriter(File file) : 创建⼀个新的 FileWriter,给定要读取的File对象。
FileWriter(String fileName) : 创建⼀个新的 FileWriter,给定要读取的⽂件的名称。
构造时使⽤系统默认的字符编码和默认字节缓冲区。
1、写出字符: write(int b) ⽅法,每次可以写出⼀个字符数据
2、写出字符数组 : write(char[] cbuf) 和 write(char[] cbuf, int off, int len) ,每次可以写出字符数组中的数据,⽤法类似FileOutputStream
3、写出字符串: write(String str) 和 write(String str, int off, int len),每次可以写出字符串中的数据,更为⽅便
因为内置缓冲区的原因,如果不关闭输出流,⽆法写出字符到⽂件中。但是关闭的流对象,是⽆法继续写出数据的。如果我们既想写出数据,⼜想继续使⽤流,就需要flush ⽅法了。
// 使⽤File对象创建流对象
File file = new File("fw.txt");
FileWriter fw = new FileWriter(file);
// 使⽤⽂件名称创建流对象
FileWriter fw = new FileWriter("fw.txt");
// 使⽤⽂件名称创建流对象
FileWriter fw = new FileWriter("fw.txt");
// 写出数据
fw.write(97); // 写出第1个字符
fw.write('b'); // 写出第2个字符
fw.write('C'); // 写出第3个字符
fw.write(30000); // 写出第4个字符,中⽂编码表中30000对应⼀个汉字。
/*
【注意】关闭资源时,与FileOutputStream不同。
如果不关闭,数据只是保存到缓冲区,并未保存到⽂件。
*/
// fw.close();
// 使⽤⽂件名称创建流对象
FileWriter fw = new FileWriter("fw.txt");
// 写出数据,通过flush
fw.write('刷'); // 写出第1个字符
fw.flush();
fw.write('新'); // 继续写出第2个字符,写出成功
fw.flush();
// 写出数据,通过close
fw.write('关'); // 写出第1个字符
fw.close();
fw.write('闭'); // 继续写出第2个字符,【报错】java.io.IOException: Stream
closed
fw.close();
// 使⽤⽂件名称创建流对象
FileWriter fw = new FileWriter("fw.txt");
// 字符串转换为字节数组
char[] chars = "你好中国".toCharArray();
// 写出字符数组
fw.write(chars);
// 写出从索引2开始,2个字节。索引2是'中',两个字节,也就是'中国'。
fw.write(b,2,2); //中国
// 关闭资源
fos.close();
// 使⽤⽂件名称创建流对象
FileWriter fw = new FileWriter("fw.txt");
// 字符串
String msg = "你好中国";
// 写出字符数组
fw.write(msg); //你好中国
// 写出从索引2开始,2个字节。索引2是'中',两个字节,也就是'中国'。
fw.write(msg,2,2); // 中国
// 关闭资源
fos.close();
缓冲流,也叫⾼效流,是对4个基本的 FileXxx 流的增强,所以也是4个流,按照数据类型分类:
字节缓冲流: BufferedInputStream , BufferedOutputStream
字符缓冲流: BufferedReader , BufferedWriter
缓冲流的基本原理,是在创建流对象时,会创建⼀个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从⽽提⾼读写的效率。
字节缓冲流
构造⽅法:
public BufferedInputStream(InputStream in) :创建⼀个 新的缓冲输⼊流。
public BufferedOutputStream(OutputStream out) : 创建⼀个新的缓冲输出流。
示例:
// 创建字节缓冲输⼊流
BufferedInputStream bis = new BufferedInputStream(new
FileInputStream("bis.txt"));
// 创建字节缓冲输出流
BufferedOutputStream bos = new BufferedOutputStream(new
FileOutputStream("bos.txt"));
public static void main(String[] args) {
// 记录开始时间
long start = System.currentTimeMillis();
// 创建流对象
try (
FileInputStream fis = new FileInputStream("jdk8.exe");
FileOutputStream fos = new FileOutputStream("copy.exe")
){
// 读写数据
int b;
while ((b = fis.read()) != -1) {
fos.write(b);
}
} catch (IOException e) {
e.printStackTrace();
}
// 记录结束时间
long end = System.currentTimeMillis();
System.out.println("普通流复制时间:"+(end - start)+" 毫秒");
}
public static void main(String[] args) {
// 记录开始时间
long start = System.currentTimeMillis();
// 创建流对象
try (
BufferedInputStream bis = new BufferedInputStream(new
FileInputStream("jdk8.exe"));
BufferedOutputStream bos = new BufferedOutputStream(new
FileOutputStream("copy.exe"));
){
// 读写数据
//int b;
//while ((b = bis.read()) != -1) {
//bos.write(b);
//}
// 读写数据
int len;
byte[] bytes = new byte[8*1024];
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0 , len);
}
} catch (IOException e) {
e.printStackTrace();
}
// 记录结束时间
long end = System.currentTimeMillis();
System.out.println("缓冲流复制时间:"+(end - start)+" 毫秒");
}
构造方法
public BufferedReader(Reader in) :创建⼀个 新的缓冲输⼊流。
public BufferedWriter(Writer out) : 创建⼀个新的缓冲输出流。
示例:
// 创建字符缓冲输⼊流
BufferedReader br = new BufferedReader(new FileReader("br.txt"));
// 创建字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
字符缓冲流的基本⽅法与普通字符流调⽤⽅式⼀致,不再阐述,我们来看它们具备的特有⽅法。
BufferedReader: public String readLine() : 读⼀⾏⽂字。
BufferedWriter: public void newLine() : 写⼀⾏⾏分隔符,由系统属性定义符号。
示例1:
// 创建流对象
BufferedReader br = new BufferedReader(new FileReader("in.txt"));
// 定义字符串,保存读取的⼀⾏⽂字
String line = null;
// 循环读取,读取到最后返回null
while ((line = br.readLine())!=null) {
System.out.print(line);
System.out.println("------");
}
// 释放资源
br.close();
示例2:
// 创建流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("out.txt"));
// 写出数据
bw.write("hello");
// 写出换⾏
bw.newLine();
bw.write("world");
bw.newLine();
bw.write("!");
bw.newLine();
// 释放资源
bw.close();
在IDEA中,使⽤ FileReader 读取项⽬中的⽂本⽂件。由于IDEA的设置,都是默认的 UTF-8编码,所以没有任何问题。但是,当读取Windows系统中创建的⽂本⽂件时,由于Windows系统的默认是GBK编码,就会出现乱码。
示例:
public class ReaderDemo {
public static void main(String[] args) throws IOException {
FileReader fileReader = new FileReader("E:\\File_GBK.txt");
int read;
while ((read = fileReader.read()) != -1) {
System.out.print((char)read);
}
fileReader.close();
}
}
输出结果:
���
那么如何读取GBK编码的⽂件呢?
转换流 java.io.InputStreamReader ,是Reader的⼦类,是从字节流到字符流的桥梁。它读取字节,并使⽤指定的字符集将其解码为字符。它的字符集可以由名称指定,也可以接受平台的默认字符集。
构造方法
InputStreamReader(InputStream in) : 创建⼀个使⽤默认字符集的字符流。
InputStreamReader(InputStream in, String charsetName) : 创建⼀个指定字符集的字符流。
示例:
// 定义⽂件路径,⽂件为gbk编码
String FileName = "E:\\file_gbk.txt";
// 创建流对象,默认UTF8编码
InputStreamReader isr = new InputStreamReader(new
FileInputStream(FileName));
// 创建流对象,指定GBK编码
InputStreamReader isr2 = new InputStreamReader(new
FileInputStream(FileName) , "GBK");
// 定义变量,保存字符
int read;
// 使⽤默认编码字符流读取,乱码
while ((read = isr.read()) != -1) {
System.out.print((char)read); // ��Һ�
}
isr.close();
// 使⽤指定编码字符流读取,正常解析
while ((read = isr2.read()) != -1) {
System.out.print((char)read);// ⼤家好
}
isr2.close();
转换流 java.io.OutputStreamWriter ,是Writer的⼦类,是从字符流到字节流的桥梁。使⽤指定
的字符集将字符编码为字节。它的字符集可以由名称指定,也可以接受平台的默认字符集。
构造⽅法
OutputStreamWriter(OutputStream in) : 创建⼀个使⽤默认字符集的字符流。
OutputStreamWriter(OutputStream in, String charsetName) : 创建⼀个指定字符集的字符流。
示例:
// 定义⽂件路径
String FileName = "out.txt";
// 创建流对象,默认UTF8编码
OutputStreamWriter osw = new OutputStreamWriter(new
FileOutputStream(FileName));
// 写出数据
osw.write("你好"); // 保存为6个字节
osw.close();
// 定义⽂件路径
String FileName2 = "out2.txt";
// 创建流对象,指定GBK编码
OutputStreamWriter osw2 = new OutputStreamWriter(new
FileOutputStream(FileName2),"GBK");
// 写出数据
osw2.write("你好");// 保存为4个字节
osw2.close();
Java 提供了⼀种对象序列化的机制。⽤⼀个字节序列可以表示⼀个对象,该字节序列包含该 对象的数据 、 对象的类型 和 对象中存储的属性 等信息。字节序列写出到⽂件之后,相当于⽂件中持久保存了⼀个对象的信息。
反之,该字节序列还可以从⽂件中读取回来,重构对象,对它进⾏反序列化。 对象的数据 、 对象的类型 和 对象中存储的数据信息,都可以⽤来在内存中创建对象。
java.io.ObjectOutputStream 类,将Java对象的原始数据类型写出到⽂件,实现对象的持久存储。
⼀个对象要想序列化,必须满⾜两个条件:
必须实现Serializable接⼝。
必须保证其所有属性均可序列化。(transient修饰为临时属性,不参与序列化)
写出对象⽅法
public final void writeObject (Object obj) : 将指定的对象写出。
示例:
public class Employee implements java.io.Serializable {
public String name;
public String address;
public transient int age; // transient瞬态修饰成员,不会被序列化
public void addressCheck() {
System.out.println("Address check : " + name + " -- " + address);
}
}
public class SerializeDemo{
public static void main(String [] args) {
Employee e = new Employee();
e.name = "zhangsan";
e.address = "guangzhou";
e.age = 20;
try {
// 创建序列化流对象
ObjectOutputStream out = new ObjectOutputStream(new
FileOutputStream("employee.txt"));
// 写出对象
out.writeObject(e);
// 释放资源
out.close();
fileOut.close();
System.out.println("序列化完成"); // 姓名,地址被序列化,年龄没有被序列化。
} catch(IOException i) {
i.printStackTrace();
}
}
}
ObjectInputStream反序列化流,将之前使⽤ObjectOutputStream序列化的原始数据恢复为对象。
如果能找到⼀个对象的class⽂件,我们可以进⾏反序列化操作,调⽤ ObjectInputStream 读取对象的⽅法,
public final Object readObject () : 读取⼀个对象。
public class DeserializeDemo {
public static void main(String [] args) {
Employee e = null;
try {
// 创建反序列化流
FileInputStream fileIn = new FileInputStream("employee.txt");
ObjectInputStream in = new ObjectInputStream(fileIn);
// 读取⼀个对象
e = (Employee) in.readObject();
// 释放资源
in.close();
fileIn.close();
}catch(IOException i) {
// 捕获其他异常
i.printStackTrace();
return;
}catch(ClassNotFoundException c) {
// 捕获类找不到异常
System.out.println("Employee class not found");
c.printStackTrace();
return;
}
// ⽆异常,直接打印输出
System.out.println("Name: " + e.name); // zhangsan
System.out.println("Address: " + e.address); // beiqinglu
System.out.println("age: " + e.age); // 0
}
}
注意:
对于JVM可以反序列化对象,它必须是能够找到class⽂件的类。如果找不到该类的class⽂件,则抛出⼀个ClassNotFoundException 异常。
当JVM反序列化对象时,能找到class⽂件,但是class⽂件在序列化对象之后发⽣了修改,那么反序列化操作也会失败,抛出⼀个 InvalidClassException 异常。
发⽣这个异常的原因,该类的序列版本号与从流中读取的类描述符的版本号不匹配 ,serialVersionUID 该版本号的⽬的在于验证序列化的对象和对应类是否版本匹配。
serialVersionUID是⼀个⾮常重要的字段,因为 Java 的序列化机制是通过在运⾏时判断类的
serialVersionUID来验证版本⼀致性的。在进⾏反序列化时,JVM 会把传来的字节流中的
serialVersionUID与本地相应实体(类)的serialVersionUID进⾏⽐较,如果相同就认为是⼀致的,可
以进⾏反序列化,否则就会出现序列化版本不⼀致的异常。
⼀般来说,定义serialVersionUID的⽅式有两种,分别为:
采⽤默认的1L,具体为private static final long serialVersionUID = 1L;
在可兼容的前提下,可以保留旧版本号,如果不兼容,或者想让它不兼容,就⼿⼯递增版本号。
1->2->3.....
根据类名、接⼝名、成员⽅法及属性等来⽣成⼀个64位的哈希字段,例如 private static final long
serialVersionUID = XXXL;
这种⽅式适⽤于这样的场景:
开发者认为每次修改类后就需要⽣成新的版本号,不想向下兼容,操作就是删除原有serialVesionUid
声明语句,再⾃动⽣成⼀下。
第⼆种能够保证每次更改类结构后改变版本号,但还是要⼿⼯去⽣成
public class Employee implements java.io.Serializable {
// 加⼊序列版本号
private static final long serialVersionUID = 1L;
public String name;
public String address;
// 添加新的属性 ,重新编译, 可以反序列化,该属性赋为默认值.
public int eid;
public void addressCheck() {
System.out.println("Address check : " + name + " -- " + address);
}
}
常用方法
public Object setProperty(String key, String value) : 保存⼀对属性。
public String getProperty(String key) :使⽤此属性列表中指定的键搜索属性值。
public Set stringPropertyNames() :所有键的名称的集合。
public void load(InputStream inStream) : 从字节输⼊流中读取键值对。
示例1:
// 创建属性集对象
Properties properties = new Properties();
// 添加键值对元素
properties.setProperty("filename", "a.txt");
properties.setProperty("length", "123");
properties.setProperty("location", "D:\\a.txt");
// 打印属性集对象
System.out.println(properties);
// 通过键,获取属性值
System.out.println(properties.getProperty("filename"));
System.out.println(properties.getProperty("length"));
System.out.println(properties.getProperty("location"));
// 遍历属性集,获取所有键的集合
Set strings = properties.stringPropertyNames();
// 打印键值对
for (String key : strings ) {
System.out.println(key+" -- "+properties.getProperty(key));
}
示例2:
// 创建属性集对象
Properties pro = new Properties();
// 加载⽂本中信息到属性集
pro.load(new FileInputStream("read.txt"));
// 遍历集合并打印
Set strings = pro.stringPropertyNames();
for (String key : strings ) {
System.out.println(key+" -- "+pro.getProperty(key));
}
小贴士:⽂本中的数据,必须是键值对形式,可以使⽤空格、等号、冒号等符号分隔。