目录
6.1.5、Serializable接口与Externalizable
1、File
构造器 | 描述 |
从父抽象路径名和子路径名字符串创建新的 File实例。 | |
通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。 | |
从父路径名字符串和子路径名字符串创建新的 File实例。 |
常用方法:
变量和类型 | 方法 | 描述 |
返回此抽象路径名的绝对路径名字符串。 | ||
返回此抽象路径名的绝对形式。 | ||
返回此抽象路径名父项的路径名字符串,如果此路径名未指定父目录,则返回 null 。 | ||
返回此抽象路径名父项的抽象路径名,如果此路径名未指定父目录,则返回 null 。 | ||
getPath() | 将此抽象路径名转换为路径名字符串。 | |
long | length() | 返回此抽象路径名表示的文件的长度。单位Byte。1024B = 1KB |
boolean | exists() | 测试此抽象路径名表示的文件或目录是否存在。 |
boolean | 测试此抽象路径名表示的文件是否为目录。 | |
boolean | isFile() | 测试此抽象路径名表示的文件是否为普通文件。 |
String[] | list() | 返回一个字符串数组,用于命名此抽象路径名表示的目录中的文件和目录。 |
File[] | 返回一个抽象路径名数组,表示此抽象路径名表示的目录中的文件。 | |
boolean | mkdir() | 创建此抽象路径名指定的目录,父目录不存在就创建不出来 |
boolean | mkdirs() | 创建此抽象路径名指定的目录,父目录不存在会把父目录创建 |
boolean | 剪切并重命名 | |
boolean | delete() | 删除此抽象路径名表示的文件或目录。删除文件要谨慎,删掉不会在回收站 |
成员属性:不同系统路径用的符号会不同,用这个替代不会出错
变量和类型 | 字段 | 描述 |
static String | 与系统相关的路径分隔符,为方便起见,表示为字符串。 | |
static char | 与系统相关的路径分隔符。 | |
static String | 系统相关的默认名称分隔符,为方便起见,表示为字符串。 | |
static char | 系统相关的默认名称分隔符。 |
2、文件过滤器+遍历文件夹
package com.syp.file.test;
import java.io.File;
import java.io.FileFilter;
/**
* @author suyiping
* @create 2021-06-23 19:33
*/
public class Test {
public static void main(String[] args) {
File file = new File("E:/");
showFiles(file);
}
static void showFiles(File file) {
File[] files = file.listFiles(new FileFilter() {
@Override
public boolean accept(File f) {
if ((f.getName().endsWith(".exe") && f.length() > 10 * 1024 * 1024) || f.isDirectory())
return true;
return false;
}
});
if (files == null || files.length == 0) {
return;
}
for (File f : files) {
//如果是文件夹,就继续往下层找
if (f.isDirectory()) {
showFiles(f);
} else {
System.out.println(f.getAbsoluteFile() + "\tSize:" + f.length() / (1024 * 1024) + "MB");
}
}
}
}
3、相对路径和绝对路径
绝对路径:从盘符开始,是一个完整的路径 例如: E://a/1.txt
相对路径:相对于项目目录的路径
4、IO流
Input:输入,输入(读)到JAVA程序
Ouput:输出,输出(写)到别的地方,例如写到系统中
分类:
按照流的方向:输入流、输出流
按照流动的数据类型:字符流(文字)、字节流(其他)
字符流和字节流:
字节流操作的基本单元为字节byte;字符流操作的基本单元为Unicode码元(char)。
字节流默认不使用缓冲区;字符流使用缓冲区。
字节流通常用于处理二进制数据,实际上它可以处理任意类型的数据,但它不支持直接写入或读取Unicode码元;字符流通常处理文本数据,它支持写入及读取Unicode码元。
用字节流读取文字,可能会出现某一个中文,占3个字节,被多次读取,就识别不出来的情况,所以要用转换流,把字节转换成字符
用字符流操作文字,需要使用flush方法刷新缓存。close方法中,也会先执行flush
顶级父类:
输出流 | 输入流 | |
字节流 | InputStream | OuputStream |
字符流 | Reader | Writer |
4.1、字节流
一切皆字节:计算机中的任何数据,都是以二进制的形式存储的,8个bit就是一个字节。在数据传输时,也都是以二进制存储的。
后续学习的任何流,在传输时,底层都是二进制(包括字符流)
4.1.1、OutputStream 抽象类
变量和类型 | 方法 | 描述 |
void | close() | 关闭此输出流并释放与此流关联的所有系统资源。关闭要尽可能早,且用完一定要关闭 |
void | flush() | 刷新此输出流并强制写出任何缓冲的输出字节。 |
static OutputStream | 返回一个新的 OutputStream ,它丢弃所有字节。 | |
void | write(byte[] b) | 将 b.length字节从指定的字节数组写入此输出流。 |
void | write(byte[] b, int off, int len) | 将从off下标开始,写出len个字节 |
abstract void | write(int b) | 将指定的字节写入此输出流。 |
FileOutputStream 实现类,通过这个流,可以向指定的文件,输出内容
构造器 | 描述 |
FileOutputStream(File file) | 创建文件输出流以写入由指定的 File对象表示的文件。 |
FileOutputStream(FileDescriptor fdObj) | 创建要写入指定文件描述符的文件输出流,该文件描述符表示与文件系统中实际文件的现有连接。 |
FileOutputStream(File file, boolean append) | 创建文件输出流以写入由指定的 File对象表示的文件。append为true,就是接着原来的往后写,为false就是把文件内容清空,重新写 |
FileOutputStream(String name) | 创建文件输出流以写入具有指定名称的文件。 |
FileOutputStream(String name, boolean append) | 创建文件输出流以写入具有指定名称的文件。 |
FileOutputStream使用构造方法指定一个File或文件路径构造一个流,如果文件不存在,会自动创建文件,除非权限不够
一个流创建之后,不管有没有append,都可以write多次,write的位置会接着上一次write结束的位置,直到关闭
4.1.2、InputputStream 抽象类
变量和类型 | 方法 | 描述 |
int | 返回可以从此输入流中无阻塞地读取(或跳过)的字节数的估计值,可以是0,或者在检测到流结束时为0。 | |
void | close() | 关闭此输入流并释放与该流关联的所有系统资源。 |
void | mark(int readlimit) | 标记此输入流中的当前位置。 |
boolean | 测试此输入流是否支持 mark和 reset方法。 | |
static InputStream | 返回一个不读取任何字节的新 InputStream 。 | |
abstract int | read() | 从输入流中读取下1个数据字节。 值字节返回int ,范围为0至255 。 如果由于到达流末尾而没有可用字节,则返回值-1 。 此方法将阻塞,直到输入数据可用,检测到流的末尾或抛出异常。 |
int | read(byte[] b) | 从输入流中读取一些字节数并将它们赋值到缓冲区数组 b 。返回实际读取的字节数。如果b的长度为零,则不读取任何字节,并返回0 ; 否则,尝试读取至少一个字节。 如果由于流位于文件末尾而没有可用字节,则返回值-1 ; 否则,至少读取一个字节并存储到b 。 |
int | read(byte[] b, int off, int len) | 从输入流 len最多 len字节的数据读入一个字节数组。 |
byte[] | 从输入流中读取所有剩余字节。 | |
int | readNBytes(byte[] b, int off, int len) | 从输入流中读取请求的字节数到给定的字节数组中。 |
byte[] | readNBytes(int len) | 从输入流中读取指定的字节数。 |
void | reset() | 将此流重新定位到上次在此输入流上调用 mark方法时的位置。 |
long | skip(long n) | 跳过并丢弃此输入流中的 n字节数据。 |
long | transferTo(OutputStream out) | 从该输入流中读取所有字节,并按读取顺序将字节写入给定的输出流。 |
FileInputStream 实现类
构造器 | 描述 |
FileInputStream(File file) | 通过打开与实际文件的连接来创建 FileInputStream ,该文件由文件系统中的 File对象 file命名。 |
FileInputStream(FileDescriptor fdObj) | 使用文件描述符 fdObj创建 FileInputStream ,该文件描述符表示与文件系统中实际文件的现有连接。 |
FileInputStream(String name) | 通过打开与实际文件的连接来创建 FileInputStream ,该文件由文件系统中的路径名 name命名。 |
FileInputStream如果没有读取到文件,不会自动创建
一个流在read之后,如果没有close,可以接着read,read的位置接着上一次read的末尾
尽量使用byte[]来读取字节,而不是单读取一个byte多次,read次数越少越好。这样速度才会快
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("E:/1.txt");
byte[] bytes = "1234567890".getBytes();
fos.write(bytes);
fos.close();
FileInputStream fis = new FileInputStream("E:/1.txt");
byte[] byte1 = new byte[2];
int len = 0;
while (len != -1) {
System.out.println(new String(byte1,0,len));
len = fis.read(byte1);
}
fis.close();
System.out.println(Arrays.toString(byte1));
}
4.2、字符流
4.2.1、Writer抽象类
变量和类型 | 方法 | 描述 |
append(char c) | 将指定的字符追加到此writer。 | |
append(CharSequence csq) | 将指定的字符序列追加到此writer。 | |
append(CharSequence csq, int start, int end) | 将指定字符序列的子序列追加到此writer。 | |
abstract void | close() | 关闭流,先冲洗它。 |
abstract void | flush() | 刷新流。 |
static Writer | 返回一个新的 Writer ,它丢弃所有字符。 | |
void | write(char[] cbuf) | 写一个字符数组。 |
abstract void | write(char[] cbuf, int off, int len) | 写一个字符数组的一部分。 |
void | write(int c) | 写一个字符。 |
void | 写一个字符串。 | |
void | 写一个字符串的一部分。 |
FileWriter 实现类
构造器 | 描述 |
FileWriter(File file) | 给 File写一个 FileWriter ,使用平台的 default charset |
FileWriter(FileDescriptor fd) | 构造一个 FileWriter给出的文件描述符,使用该平台的 default charset 。 |
FileWriter(File file, boolean append) | 在给出要写入的 FileWriter下构造 File ,并使用平台的 default charset构造一个布尔值,指示是否附加写入的数据。 |
FileWriter(File file, Charset charset) | 构造一个FileWriter给予File编写和charset 。 |
FileWriter(File file, Charset charset, boolean append) | 构造FileWriter给出File写入, charset和一个布尔值,指示是否附加写入的数据。 |
FileWriter(String fileName) | 构造一个 FileWriter给出文件名,使用平台的 default charset |
FileWriter(String fileName, boolean append) | 使用平台的 default charset构造一个 FileWriter给定一个文件名和一个布尔值,指示是否附加写入的数据。 |
FileWriter(String fileName, Charset charset) | 构造一个FileWriter给出文件名和charset 。 |
FileWriter(String fileName, Charset charset, boolean append) | 构造一个FileWriter给定一个文件名, charset和一个布尔值,指示是否附加写入的数据。 |
4.2.2、Reader抽象类
变量和类型 | 方法 | 描述 |
abstract void | close() | 关闭流并释放与其关联的所有系统资源。 |
void | mark(int readAheadLimit) | 标记流中的当前位置。 |
boolean | 判断此流是否支持mark()操作。 | |
static Reader | 返回不读取任何字符的新 Reader 。 | |
int | read() | 读一个字符。 |
int | read(char[] cbuf) | 将字符读入数组。 |
abstract int | read(char[] cbuf, int off, int len) | 将字符读入数组的一部分。 |
int | read(CharBuffer target) | 尝试将字符读入指定的字符缓冲区。 |
boolean | ready() | 判断此流是否可以读取。 |
void | reset() | 重置流。 |
long | skip(long n) | 跳过字符。 |
long | transferTo(Writer out) | 读取此阅读器中的所有字符,并按照读取的顺序将字符写入给定的编写器。 |
FileReader 实现类
构造器 | 描述 |
FileReader(File file) | 使用平台 FileReader ,在 File读取时创建一个新的 FileReader 。 |
FileReader(FileDescriptor fd) | 使用平台 default charset创建一个新的 FileReader ,给定 FileDescriptor进行读取。 |
FileReader(File file, Charset charset) | 创建一个新的FileReader ,给出File读取和charset 。 |
FileReader(String fileName) | 使用平台 default charset创建一个新的 FileReader ,给定要读取的文件的 名称 。 |
FileReader(String fileName, Charset charset) | 给定要读取的文件的名称和FileReader ,创建一个新的FileReader 。 |
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("E:/b.txt");
fw.write("龘龘龘龘龖龖龘惡惡辶辶");
fw.append("11111").append("22222").append("33333");
fw.flush();
fw.close();
FileReader fr = new FileReader("E:/b.txt");
char[] chars = new char[2];
int lenth = 0;
while (lenth != -1) {
System.out.println(new String(chars, 0, lenth));
lenth = fr.read(chars);
}
}
BufferedReader和FileReader区别
BufferedReader(FileReader("filename"))将FileReader包装后,再使用read(char[] chbf)读取,可以将文件内容装入缓存。而FileReader则会频繁使用底层IO,造成阻塞其他需要访问IO的操作,所以读取文件BufferedReader比FileReader更高效。
BufferedReader提供了readLine方法。可以读取一整行为一个String
4.3、转换流。将字节流装饰为字符流:使用装饰者设计模式
InputStreamReader
构造器 | 描述 |
创建一个使用默认字符集的InputStreamReader。 | |
InputStreamReader(InputStream in, String charsetName) | 创建一个使用指定charset的InputStreamReader。 |
InputStreamReader(InputStream in, Charset cs) | 创建一个使用给定charset的InputStreamReader。 |
InputStreamReader(InputStream in, CharsetDecoder dec) | 创建一个使用给定charset解码器的InputStreamReader。 |
OutputStreamReader
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("E:/b.txt");
InputStreamReader isr = new InputStreamReader(fis, "utf-8");
while (true) {
int word = isr.read();
if (word == -1) {
break;
}
System.out.println((char)word);
}
FileOutputStream fos = new FileOutputStream("E:/b.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos);
osw.write("床前明月光");
osw.flush();
osw.close();
}
4.4、字符输出打印流、缓冲读取流
PrintStream
PrintWriter 也可以转换字节流进行输出
public static void main(String[] args) throws FileNotFoundException {
PrintStream ps = new PrintStream("E:/c2.txt");
ps.println("11111");
ps.println("22222");
ps.println("33333");
ps.close();
PrintWriter pw = new PrintWriter("E:/c1.txt");
pw.println("55555");
pw.println("55555");
pw.println("55555");
pw.flush();
pw.close();
FileOutputStream fos = new FileOutputStream("E:/b.txt");
PrintWriter pw1 = new PrintWriter(fos);
pw1.println("bbbbbbbbb");
pw1.flush();
pw1.close();
}
BufferedReader
可以将FileReader转为BufferedReader,进行读取行
读取行readLine读完时,会返回null
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("E:/c2.txt");
BufferedReader br = new BufferedReader(fr);
while (true) {
String str = br.readLine();
if (str == null) {
break;
}
System.out.println(str);
}
}
4.5、输出错误日志
public static void main(String[] args) throws FileNotFoundException {
String s = null;
try {
s.toString();
} catch (Exception e) {
PrintWriter pw = new PrintWriter("E:/bugs.txt");
e.printStackTrace(pw);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
pw.println("报错时间:" + sdf.format(new Date()));
pw.close();
}
}
5、Properties
本质上是一个HashTable,操作与HashMap一致
变量和类型 | 方法 | 描述 |
getProperty(String key) | 在此属性列表中搜索具有指定键的属性。 | |
getProperty(String key, String defaultValue) | 在此属性列表中搜索具有指定键的属性。 | |
void | list(PrintStream out) | 将此属性列表打印到指定的输出流。 |
void | list(PrintWriter out) | 将此属性列表打印到指定的输出流。 |
void | load(InputStream inStream) | 从输入字节流中读取属性列表(键和元素对)。 |
void | 以简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。 | |
void | loadFromXML(InputStream in) | 将指定输入流上的XML文档表示的所有属性加载到此属性表中。 |
Enumeration<?> | 返回此属性列表中所有键的枚举,如果尚未从主属性列表中找到相同名称的键,则包括默认属性列表中的不同键。 | |
void | save(OutputStream out, String comments) | 已过时。现在用store 如果在保存属性列表时发生I / O错误,则此方法不会抛出IOException。 |
setProperty(String key, String value) | 调用 Hashtable方法 put 。 | |
void | store(OutputStream out, String comments) | 将此 Properties表中的此属性列表(键和元素对)以适合使用 load(InputStream)方法加载到 Properties表的格式写入输出流。 |
void | 将此 Properties表中的此属性列表(键和元素对)以适合使用 load(Reader)方法的格式写入输出字符流。 | |
void | storeToXML(OutputStream os, String comment) | 发出表示此表中包含的所有属性的XML文档。 |
void | storeToXML(OutputStream os, String comment, String encoding) | 使用指定的编码发出表示此表中包含的所有属性的XML文档。 |
void | storeToXML(OutputStream os, String comment, Charset charset) | 使用指定的编码发出表示此表中包含的所有属性的XML文档。 |
从此属性列表返回一组不可修改的键,其中键及其对应的值是字符串,如果尚未从主属性列表中找到相同名称的键,则包括默认属性列表中的不同键。 |
public static void main(String[] args) throws IOException {
Properties properties = new Properties();
properties.put("userName", "11111");
properties.put("password", "666666");
FileWriter fw = new FileWriter("E:/userInfo.properties");
properties.store(fw,"啊啊啊啊龘龘");
fw.flush();
fw.close();
Properties p2 = new Properties();
FileReader r = new FileReader("E:/userInfo.properties");
p2.load(r);
System.out.println(p2.getProperty("userName"));
System.out.println(p2.get("username"));
System.out.println(p2.get("password"));
r.close();
}
6、序列化与反序列化
序列化:把对象存到文件
反序列化:把文件转为对象
要序列化的类型,需要实现Serializable接口。要序列化的类型中的属性如果是一个类,也要实现Serializable接口
存入的如果是集合,拿出来也要用对应的集合装
public class Test9 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//写入数据
/*LinkedList<Book> list = new LinkedList<>();
Book book1 = new Book("第一本书", "语文书");
Book book2 = new Book("第二本书", "数学书");
Book book3 = new Book("第三本书", "英语书");
list.add(book1);
list.add(book2);
list.add(book3);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:/books.txt"));
oos.writeObject(list);
oos.close();*/
//读取数据
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:/books.txt"));
LinkedList<Book> bookList = (LinkedList<Book>) ois.readObject();
System.out.println(bookList.toString());
}
static class Book implements Serializable {
private String name;
private String info;
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", info='" + info + '\'' +
'}';
}
public Book() {
}
public Book(String name, String info) {
this.name = name;
this.info = info;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
}
6.1、序列化中忽略不想序列化的属性
6.1.1、transient关键字
在实现序列化接口的类的属性前 加上 transient关键字 priavate transient String name。该属性就会在序列化的时候被忽略
6.1.2、static关键字
用static修饰的字段,也不会被序列化,但是这个值因为是static的,会在JVM中和这个字段所属的类进行绑定,如果这个属性被赋值过,且JVM没有关闭,创建类时,一样会读取到这个属性,且是唯一的。
public class Test9 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//写入数据
LinkedList<Book> list = new LinkedList<>();
Book book1 = new Book("第一本书", "语文书");
Book book2 = new Book("第二本书", "数学书");
Book book3 = new Book("第三本书", "英语书");
list.add(book1);
list.add(book2);
list.add(book3);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:/books.txt"));
oos.writeObject(list);
oos.close();
//读取数据
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:/books.txt"));
Collection<Object> bookList = Collections.singleton(ois.readObject());
System.out.println(bookList.toString());
}
static class Book implements Serializable {
private transient String name;
private static String info;
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", info='" + info + '\'' +
'}';
}
public Book() {
}
public Book(String name, String info) {
this.name = name;
this.info = info;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
}
输出结果:
[[Book{name='null', info='英语书'}, Book{name='null', info='英语书'}, Book{name='null', info='英语书'}]]
6.1.3、默认方法实现序列化
private void writeObject(ObjectOutputStream out){}
private void readObject(ObjectInputStream in){}
在要序列化的类中,手动添加 写入序列化方法或者读取序列化方法,也能达到把想序列化的属性,进行序列化的效果,不受transient的影响
该方法必须是 private void的
但是static的原则,如上,依然存在
package com.syp.file.test;
import java.io.*;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
/**
* @author suyiping
* @create 2021-06-24 21:25
*/
public class Test9 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//写入数据
LinkedList<Book> list = new LinkedList<>();
Book book1 = new Book("第一本书", "语文书", 10);
Book book2 = new Book("第二本书", "数学书", 11);
Book book3 = new Book("第三本书", "英语书", 12);
list.add(book1);
list.add(book2);
list.add(book3);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:/books.txt"));
oos.writeObject(list);
oos.close();
//读取数据
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:/books.txt"));
Collection<Object> bookList = Collections.singleton(ois.readObject());
System.out.println(bookList.toString());
}
static class Book implements Serializable {
private transient String name;
private static String info;
private Integer age;
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", info='" + info + '\'' +
", age=" + age +
'}';
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.writeObject(name);
// out.writeObject(age);
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
name = (String) in.readObject();
// age = (Integer) in.readObject();
}
public Book() {
}
public Book(String name, String info, int age) {
this.name = name;
this.info = info;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
}
输出结果
[[Book{name='第一本书', info='英语书', age=null}, Book{name='第二本书', info='英语书', age=null}, Book{name='第三本书', info='英语书', age=null}]]
6.1.4、Externalizable接口,实现序列化
与6.1.3中使用方法类似,作为了解就行,不常用
package com.syp.file.test;
import java.io.*;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
/**
* @author suyiping
* @create 2021-06-24 21:25
*/
public class Test9 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//写入数据
LinkedList<Book> list = new LinkedList<>();
Book book1 = new Book("第一本书", "语文书", 10);
Book book2 = new Book("第二本书", "数学书", 11);
Book book3 = new Book("第三本书", "英语书", 12);
list.add(book1);
list.add(book2);
list.add(book3);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:/books.txt"));
oos.writeObject(list);
oos.close();
//读取数据
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:/books.txt"));
Collection<Object> bookList = Collections.singleton(ois.readObject());
System.out.println(bookList.toString());
}
static class Book implements Externalizable {
private transient String name;
private static String info;
private Integer age;
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", info='" + info + '\'' +
", age=" + age +
'}';
}
public Book() {
}
public Book(String name, String info, int age) {
this.name = name;
this.info = info;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(name);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
name = (String) in.readObject();
}
}
}
6.1.5、Serializable接口与Externalizable
区别 | Serializable | Externalizable |
实现复杂度 | 实现简单 | 实现复杂 |
执行效率 | 所有对象统一保存,速度相对慢 | 部分保存,速度相对快 |
保存信息 | 全部保存,保存时空间相对使用较大 | 部分保存,空间使用相对较小 |
使用频率 | 高 | 低,面试有可能问到 |
7、try-with-resources
JDK1.7之前
public static void main(String[] args) {
FileReader fr =null;
try {
fr = new FileReader("E:/1.txt");
int c = fr.read();
if (c != -1) {
System.out.println((char) c);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
JDK1.7时 在try()中可以声明一个类,该类必须是实现了Closeable接口的,结束try后,会自动close
public static void main(String[] args) throws FileNotFoundException {
try (FileReader fr = new FileReader("E:/1.txt")) {
int c = fr.read();
if (c != -1) {
System.out.println((char) c);
}
} catch (IOException e) {
e.printStackTrace();
}
}
JDK9 用分号隔开。可以放入多个类
public static void main(String[] args) throws FileNotFoundException {
FileReader fr = new FileReader("E:/1.txt");
FileInputStream fis = new FileInputStream("E:/1.txt");
try (fr; PrintWriter pw =new PrintWriter("E:/1.txt");fis) {
int c = fr.read();
if (c != -1) {
System.out.println((char) c);
}
} catch (IOException e) {
e.printStackTrace();
}
}