1.对象字节流(ObjectInputStream\ObjectOutputStream)
在学习对象字节流之前,先来了解一个接口java.io.Serializable
JAVA允许我们在内存中创建可重复使用的对象,但是,他们的生命仅仅只和虚拟机运行时间一样长。
一旦JVM停止运行,对象随之被清除,如何才能我们的对象永久保存?
java.io.Serializable接口可以使我们的对象永久的持久化
java.io.Serializable可以将一个对象(标志对象的类型)及其状态转换为字节码,保存起来(可以保存在数
据库,内存,文件等),然后可以在适当的时候再将其状态恢复(也就是反序列化), serialization 不但可
以在本机做,而且可以经由网络操作。它自动屏蔽了操作系统的差异,字节顺序等
java.io.Serializable接口没有任何方法属性域,实现它的类只是从语义上表明自己是可以序列化的
在对一个 Serializable(可序列化)对象进行重新装配的过程中,不会调用任何构造器(甚至默
认构造器)。整个对象都是通过从 InputStream 中取得数据恢复的
如是要一个类是可序列化的,那么它的子类也是可序列化的
被transient修饰的数据不能序列化
serialVersionUID:
为了解决对象反序列化的兼容性问题,如果没有提供serialVersionUID,对象序列化后存到硬盘上之后,
再增加或减少类的filed。这样,当反序列化时,就会出现Exception,造成不兼容问题。但当serialVersionUID
相同时,它就会将不一样的field以type的缺省值反序列化。这样就可以避开不兼容问题
Externalizable接口:
Externalizable继承于Serializable,当使用该接口时,序列化的细节需要由程序员去完成。若writeExternal()与readExternal()方法未作任何处理,那么该序列化行为将不会保存/读取任何一个字段。出结果中所有字段的值均为空。另外,若使用Externalizable进行序列化,当读取对象时,会调用被序列化类的无参构造器去创建一个新的对象,然后再将被保存对象的字段的值分别填充到新对象中。由于这个原因,实现Externalizable接口的类必须要提供一个无参的构造器,且它的访问权限为public
ObjectInputStream 与 ObjectOutputStream这两个包装类可用于输入流中读取对象类数据和将对象类型的数据写入到底层输入流 。ObjectInputStream 与 ObjectOutputStream 类所读写的对象必须实现了 Serializable 接口。需要注意的是:对象中的 transient 和 static 类型的成员变量不会被读取和写入
构造方法:
public ObjectInputStream(InputStream in)
public ObjectOutputStream(OutputStream out)
用于序列化和反序列化的方法
public final void writeObject(Object obj)
public final Object readObject()
注意两个异常:
java.io.NotSerializableException
java.io.EOFException
public static void main(String[] args) {
ObjectOutputStream oos = null;
FileOutputStream fos = null;
try {
fos = new FileOutputStream(new File("E:\\test.dat"));
oos = new ObjectOutputStream(fos);
oos.writeObject(new Person("jim",23));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException e1) { e1.printStackTrace(); }
}
if (fos != null) {
try {
fos.close();
} catch (IOException e2) { e2.printStackTrace(); }
}
}
}
public static void main(String[] args) {
FileInputStream fis = null;
ObjectInputStream ois = null;
try {
fis = new FileInputStream("E:\\test.dat");
ois = new ObjectInputStream(fis);
Person p = (Person) ois.readObject();
System.out.println(p);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e1) { e1.printStackTrace(); }
}
if (ois != null) {
try {
ois.close();
} catch (IOException e2) { e2.printStackTrace(); }
}
}
}
2.文件字符流
文件字符流: FileReader和FileWriter用于文本文件的输入/输出处理
FileReader是InputStreamReader的子类,而InputStreamReader是Reader的子类
FileWriter是OutputStreamWriter的子类,而OutputStreamWriter则是Writer的子类
构造方法:
文件字符流: FileReader和FileWriter用于文本文件的输入/输出处理
FileReader的常用方法:
int read():读取单个字符。返回字符的整数值,如果已经到达文件尾,则返回-1.
int read(char[] cbuf):将字符读入cbuf字符数组。返回读取到的字符数,如果已经到达文件尾,则返回-1.
int read(char[] cbuf,int off,int len):将读取到的字符存放到cbuf字符数组从off标识的偏移位置开始处,最多读取len个字符
FileWriter的常用方法:
void writer(int c):向文件中写入正整数c代表的单个字符。
void writer(char[] cbuf):向文件中写入字符数组cbuf。
void writer(char[] cbuf,int off, in len):向文件中写入字符数组cbuf从偏移位置off开始的len个字符。
void writer(String str):向文件中写入字符串str,注意此方法不会在写入完毕之后自动换行。
void writer(String str,int off,int len):向文件中写入字符串str的从位置off开始、长度为len的一部分子串。
Writer append(char c):向文件中追加单个字符c。
void flush():刷新字符输出流缓冲区。
void close():关闭字符输出流
文件字符流: FileReader和FileWriter用于文本文件的输入/输出处理
案例:
public static void main(String[] args) throws IOException {
File file = new File("E://Hello.txt");
// 创建文件
file.createNewFile();
// creates a FileWriter Object
FileWriter writer = new FileWriter(file);
// 向文件写入内容
writer.write("This\n is\n an\n example\n");
writer.flush();
writer.close();
// 创建 FileReader 对象
FileReader fr = new FileReader(file);
char[] a = new char[50];
fr.read(a); // 读取数组中的内容
for (char c : a)
System.out.print(c); // 一个一个打印字符
fr.close();
}
3.缓冲流
缓冲流: FileReader和FileWriter类以字符为单位进行数据读/写操作,数据的传输效率很低
BufferedReader和BufferedWriter类以缓冲流方式进行数据读/写操作,提供读取或写入一行字符串的方法,它们自己配有缓冲区
BufferedReader继承自Reader抽象类,创建对象时可以设置一个缓冲区
BufferedWriter继承自Writer抽象类,创建对象时可以设置一个缓冲区
BufferedReader主要方法:
int read();读取单个字符
int read(char[] cbuf,int off,int len);将字符读入到数组的某一部分。返回读取的字符数。达到尾部 ,返回-1
String readLine(); 读取一个文本行
void close(); 关闭该流。并释放与该流相关的所有资源
BufferedWriter主要方法:
void write(char ch); 写入单个字符。
void write(char []cbuf,int off,int len) 写入字符数据的某一部分。
void write(String s,int off,int len) 写入字符串的某一部分。
void newLine() 写入一个行分隔符。
void flush(); 刷新该流中的缓冲。将缓冲数据写到目的文件中去。
void close(); 关闭此流,再关闭前会先刷新他
案例:
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("D:\\demo1.txt");
FileWriter fw = new FileWriter("E:\\demo.txt");
BufferedReader bufr = new BufferedReader(fr);
BufferedWriter bufw = new BufferedWriter(fw);
//一行一行的读和写。
String line = null;
while((line = bufr.readLine()) != null){
bufw.write(line);
bufw.newLine();
bufw.flush();
}
/* 一个一个字节的读写。
int ch = 0;
while((ch = bufr.read())!=-1){
bufw.write(ch);
}*/
bufr.close();
bufw.close();
}
4.字符输入输出流
PrintWriter:向文本输出流打印对象的格式化表示形式。此类实现在PrintStream中的所有 与PrintStream类不同,如果启用了自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操作,而不是每当正好输出换行符时才完成。这些方法使用平台自有的行分隔符概念,而不是换行符。 此类中的方法不会抛出 I/O 异常,尽管其某些构造方法可能抛出异常。客户端可能会查询调用checkError()是否出现错误
public static void main(String[] args) throws IOException {
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("D:\\HelloWorld.html")));
out.println("");
out.println("