Java 进阶(5) Java IO流
⼀、File类
概念:代表物理盘符中的⼀个⽂件或者⽂件夹。
常见方法:
方法名 | 描述 |
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接口
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() {@Overridepublic 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);}}}
}
⼆、什么是IO
⽣活中,你肯定经历过这样的场景。当你编辑⼀个⽂本⽂件,忘记了ctrl+s ,可能⽂件就⽩⽩编辑了。当你电脑上插⼊⼀个U盘,可以把⼀个视频,拷⻉到你的电脑硬盘⾥。那么数据都是在哪些设备上的呢?键盘、内存、硬盘、外接设备等等。
我们把这种数据的传输,可以看做是⼀种数据的流动,按照流动的⽅向,以内存为基准,分为输⼊input 和输出output ,即流向内存是输⼊流,流出内存的输出流。
Java中I/O操作主要是指使⽤java.io包下的内容,进⾏输⼊、输出操作。输⼊也叫做读取数据,输出也叫做作写出数据。
三、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) :将指定的字节输出流。
FileOutputStream类
构造⽅法:
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类
构造⽅法:
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类
构造方法
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类
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"));
效率PK
基本流示例:
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(newFileInputStream("jdk8.exe"));BufferedOutputStream bos = new BufferedOutputStream(newFileOutputStream("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编码的⽂件呢?
InputStreamReader类
转换流 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();
OutputStreamWriter类
转换流 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 提供了⼀种对象序列化的机制。⽤⼀个字节序列可以表示⼀个对象,该字节序列包含该 对象的数据 、 对象的类型 和 对象中存储的属性 等信息。字节序列写出到⽂件之后,相当于⽂件中持久保存了⼀个对象的信息。
反之,该字节序列还可以从⽂件中读取回来,重构对象,对它进⾏反序列化。 对象的数据 、 对象的类型 和 对象中存储的数据信息,都可以⽤来在内存中创建对象。
ObjectOutputStream类
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(newFileOutputStream("employee.txt"));// 写出对象out.writeObject(e);// 释放资源out.close();fileOut.close();System.out.println("序列化完成"); // 姓名,地址被序列化,年龄没有被序列化。} catch(IOException i) {i.printStackTrace();}}
}
ObjectInputStream类
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); // zhangsanSystem.out.println("Address: " + e.address); // beiqingluSystem.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);}
}
九、Properties属性类
常用方法
public Object setProperty(String key, String value) : 保存⼀对属性。
public String getProperty(String key) :使⽤此属性列表中指定的键搜索属性值。
public Set<String> 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<String> 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<String> strings = pro.stringPropertyNames();
for (String key : strings ) {System.out.println(key+" -- "+pro.getProperty(key));
}
小贴士:⽂本中的数据,必须是键值对形式,可以使⽤空格、等号、冒号等符号分隔。
相关文章:

Java 进阶(5) Java IO流
⼀、File类 概念:代表物理盘符中的⼀个⽂件或者⽂件夹。 常见方法: 方法名 描述 createNewFile() 创建⼀个新文件。 mkdir() 创建⼀个新⽬录。 delete() 删除⽂件或空⽬录。 exists() 判断File对象所对象所代表的对象是否存在。 getAbsolute…...

“终于我从字节离职了...“一个年薪40W的测试工程师的自白...
”我递上了我的辞职信,不是因为公司给的不多,也不是因为公司待我不好,但是我觉得,我每天看中我憔悴的面容,每天晚上拖着疲惫的身体躺在床上,我都不知道人生的意义,是赚钱吗?是为了更…...

设计模式之策略模式(C++)
作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 一、策略模式是什么? 策略模式是一种行为型的软件设计模式,针对某个行为,在不同的应用场景下&…...

从工厂普工到Python女程序员,聊聊这一路我是如何逆袭的?
我来聊聊我是如何从一名工厂普工,到国外程序员的过程,这里面充满了坎坷。过去我的工作是在工厂的流水线上,我负责检测电池的正负极。现如今我每天从早上6:20起床,6点四五十分出发到地铁站,7:40到公司。我会给自己准备一…...

全国青少年信息素养大赛2023年python·选做题模拟二卷
目录 打印真题文章进行做题: 全国青少年电子信息智能创新大赛 python选做题模拟二卷 一、单选题 1. numbers = [1, 11, 111, 9], 运行numbers.sort() 后,运行numbers.reverse() numbers会变成?( )...

分布式事务Seata原理
Seata 是一款开源的分布式事务解决方案,致力于提供高性能与简单易用的分布式事务服务,为用户提供了 AT、TCC、SAGA 和 XA 几种不同的事务模式。Seata AT模式是基于XA事务演进而来,需要数据库支持。AT 模式的特点就是对业务无入侵式࿰…...

用ChatGPT怎么赚钱?普通人用这5个方法也能赚到生活费
ChatGPT在互联网火得一塌糊涂,因为它可以帮很多人解决问题。比如:帮编辑人员写文章,还可以替代程序员写代码,帮策划人员写文案策划等等。ChatGPT这么厉害,能否用它来赚钱呢?今天和大家分享用ChatGPT赚钱的5…...

( “树” 之 DFS) 110. 平衡二叉树 ——【Leetcode每日一题】
110. 平衡二叉树 给定一个二叉树,判断它是否是高度平衡的二叉树。 本题中,一棵高度平衡二叉树定义为: 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。 示例 1: 输入:root [3,9,20,null,null,15,7] …...

nvm软件使用-同一个环境下控制多个不同node版本
1.使用场景 nvm是一个用于管理Node.js版本的工具,它可以让你在同一台机器上安装和切换不同的Node.js版本。使用nvm的好处有以下几点: 1.1.nvm可以让你轻松地测试你的代码在不同的Node.js版本下的兼容性和性能,避免因为版本差异导致的问题。…...

连续两个南航的研究生面试出了从来没出现过的问题,本科和研究生都是计算机专业的,竟然说static是不可更改的。
最近面试人数有点多,面试有点频繁,因此发现了一些学生普遍会发生的错误,可以说是很离谱。 因为做了十多年的面试官,无论是大中小厂的面试,还是社招、校招。 从来没有遇到过这样的情况,而且发生在两个南航…...

How to install nacos/nacos-server:v2.1.2-slim with docker
今天给大家介绍一下如何基于Docker的nacos/nacos-server:v2.1.2-slim镜像安装nacos 1、Data Source 我们需要从nacos的github官网下载nacos 2.12发布包 nacos-server-2.1.2.tar.gznacos-server-2.1.2.zip 这里以nacos-server-2.1.2.tar.gz为例来介绍,解压后我们…...

Rust社区引发舆论危机,问题到底出在哪儿?
围绕开源的法律问题,讨论焦点往往集中在开源许可证、软件著作权等方面,商标的讨论却极少引人关注。事实上,关于开源软件以及开源软件的衍生产品的商标使用情况往往处于某种灰色地带。 最近,Rust基金会正在就更新的商标政策征求反馈…...

C++算法恢复训练之归并排序
归并排序(Merge Sort)是一种基于分治思想的排序算法,它将待排序数组分成两个子数组,然后对这两个子数组分别进行排序,最后将两个已排序的子数组合并成一个有序数组。归并排序是一种稳定的排序算法,具体体现…...

使用Process Explorer和Clumsy工具定位软件高CPU占用问题
目录 1、问题描述 2、使用Process Explorer初步找到CPU占用高的原因 3、使用Clumsy工具在公司内网环境复现了问题...

为何巴菲特和马斯克站在了一起?
股神巴菲特虽然非常传奇,但是马斯克对其并不感冒。马斯克曾经在一档电视节目中表示,实业才是王道,埋怨金融业抢走太多人才和精英,暗指巴菲特为年轻人做了错误示范。当然,巴菲特的投资非常厉害,但也有失手的…...

企业数字化转型全是坑?这几篇数字化转型成功案例,减少70%损失
这篇给大家整理了200企业数字化转型案例合集,涵盖了制造、建筑、教育、零售、互联网等10行业的大中小型企业数字化转型思路,希望对大家有所帮助。 案例全部整合在这篇文章中,点击即可查看>>数字化干货资料合集! 01 首先&…...

13.Java面向对象----嵌套类
Java面向对象—嵌套类、内部类、匿名类 一、static静态 在《Java编程思想》有这样一段话: “static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来…...

Redis数据迁移过程,使用jedis客户端发送命令,需要注意string和byte类型的命令,如果使用的转换字符编码不一致,会导致丢数据
1.了解String与byte之间存在的字符编码映射规则(java为例) string与byte来回转换,需要指定一样字符编码规则 详细原因请参考:关于Java中bytes到String的转换-阿里云开发者社区 简单来说 (1)string和by…...

第六章 IA-32指令类型
IA-32指令类型1、传送指令1.1、常用传送指令1.1.1、通用数据传送指令1.2、传送指令执行过程2、定点算术运算指令2.1、常用定点运算指令2.2、加法运算的底层实现举例2.3、加法指令和乘法指令举例3、按位运算指令3.1、逻辑运算和移位运算3.2、按位运算指令举例4、控制转移指令4.1…...

基于BenchmarkSQL的Oracle数据库tpcc性能测试
基于BenchmarkSQL的Oracle数据库tpcc性能测试安装BenchmarkSQL及其依赖安装软件依赖编译BenchmarkSQLBenchmarkSQL props文件配置数据库用户配置BenchmarkSQL压测装载测试数据TPC-C压测(固定事务数量)TPC-C压测(固定时长)生成测试…...

Dapr和Rainbond集成,实现云原生BaaS和模块化微服务开发
背景 Dapr 是一个开源的分布式应用运行时,帮助开发者构建松耦合的分布式应用程序,具有良好的可扩展性和可维护性。Rainbond 是一款企业级的云原生应用管理平台,提供了丰富的功能和工具,方便开发者管理和部署应用。Rainbond 和 Da…...

全国青少年信息素养大赛2023年python·选做题模拟五卷
目录 下载打印文档做题: 全国青少年电子信息智能创新大赛 python选做题模拟五卷 一、单选题 1. 对于数列3,8,11,15,17,19,25,30,44,采用“二分查找”法查找8,需要查找多少次?( ) A、5...

itop-3568开发板驱动学习笔记(18)tasklet 机制
《【北京迅为】itop-3568开发板驱动开发指南.pdf》 学习笔记 文章目录tasklet 简介tasklet 结构体tasklet 初始化使能 tasklet失能 tasklettasklet 调度函数tasklet 取消调度函数tasklet 实验tasklet 简介 Tasklets 机制是linux中断处理机制中的软中断延迟机制。在linux中存在着…...

全国青少年电子信息智能创新大赛(复赛)python·模拟二卷
目录 编程题一 答案解析: 打印题目下载做题: 全国青少年电子信息智能创新大赛(复赛)python模拟二卷 编程题一 第一题:描述 输入两个整数,比较它们的大小。 输入 一行,包含两个整数x和y,中间用单个空格隔开。 0<= x<2^32,-2^31 <= y<2^31。 输出...

对标ChatGPT的开源中文方案
目录 前言 一、Meta发布大语言模型LLaMA 二、斯坦福基于 Meta 的 LLaMA 7B 模型微调出Alpaca 三、基于TencentPretrain训练中文LLaMA大规模语言模型 四、基于斯坦福Alpaca训练中文对话大模型BELLE 五、 清华开源项目ChatGLM中文对话模型 六、基于LLaMA的开源中文语言模型…...

9.Java面向对象----封装
Java面向对象—封装 面向对象简称 OO(Object Oriented),20 世纪 80 年代以后,有了面向对象分析(OOA)、 面向对象设计(OOD)、面向对象程序设计(OOP)等新的系统…...

【react 全家桶】组合组件
本人大二学生一枚,热爱前端,欢迎来交流学习哦,一起来学习吧。 <专栏推荐> 🔥:js专栏 🔥:vue专栏 🔥:react专栏 文章目录09 【组合组件】1.包含关系2.特例关系问题…...

VUE_学习笔记
一、 xx 二、模板语法 1.模板语法之差值语法 :{{ }} 主要研究:{{ 这里可以写什么}} 在data中声明的变量、函数等都可以。常量只要是合法的javascript表达式,都可以。模板表达式都被放在沙盒中,只能访问全局变量的一个白名单&a…...

【分布式事务AT模式 SpringCloud集成Seata框架】分布式事务框架Seata详细讲解
前言 上篇文章我们讲述了如何启动seata的本地服务,并且注册到nacos使用,这篇文章将在SpringCloud中整合Seata框架 上篇文章传送门:https://blog.csdn.net/Syals/article/details/130102851?spm1001.2014.3001.5501 本篇主要内容ÿ…...

系统集成项目管理工程师软考第三章习题(每天更新)
第一章指路:系统集成项目管理工程师软考第一章习题(已完结)_程序猿幼苗的博客-CSDN博客 第二章指路:系统集成项目管理工程师软考第二章习题(已完结)_程序猿幼苗的博客-CSDN博客 第3章信息系统集成专业技术…...