1.字符流
1)编码问题;
2)认识文本和文本文件:Java的文本(char)是16位无符号整数,是字符的Unicode编码(双字节编码);文件是byte byte byte...的数据序列;文本文件是文本(char)序列按照某种编码方案(UTF-8、UTF-16、GBK)序列化为byte的存储结果;
3)字符流(Reader/Writer):字符的处理,一次处理一个字符,字符的底层仍然是基本的字节序列;InputStreamReader→完成byte流解析为char流,按照编码解析,字符流操作的是文本、文本文件;OutputStreamWriter→提供char流到byte流,按照编码处理;
package com.luna.base;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class ReadAndWriteTest {
public static void main(String[] args) throws IOException{
FileInputStream in = new FileInputStream("/Users/Gandoph/workspace/BasaInfo/src/file/log.dat");
InputStreamReader isr = new InputStreamReader(in,"gbk"); //默认项目编码
FileOutputStream out = new FileOutputStream("/Users/Gandoph/workspace/BasaInfo/src/file/log.dat");
OutputStreamWriter osw = new OutputStreamWriter(out, "gbk");
// int c;
// while((c=isr.read())!=-1){
// System.out.print((char)c);
// }
/*
* 批量读取放入buffer这个字符数组,从第0个位置开始放置,最多放buffer.length个
* 返回的是读到的字符的个数
*/
char[] buffer = new char[8*1024];
int c;
while((c=isr.read(buffer,0,buffer.length))!=-1){
String s = new String(buffer,0,c);
System.out.print(s);
osw.write(buffer,0,c);
osw.flush();
}
isr.close();
osw.close();
}
}
4)FileReader/FileWriter
package com.luna.base;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class FrAndFwTest {
public static void main(String[] args) throws IOException{
FileReader fr = new FileReader("/Users/Gandoph/workspace/BasaInfo/src/file/log.dat");
//参数true表示在源文件后面追加
FileWriter fw = new FileWriter("/Users/Gandoph/workspace/BasaInfo/src/file/log1.dat", true);
char[] buffer = new char[2056];
int c;
while((c = fr.read(buffer, 0, buffer.length))!=-1){
fw.write(buffer,0,c);
fw.flush();
}
fr.close();
fw.close();
}
}
5)BufferedReader→readLine()一次读一行,BufferedWriter/PrintWriter→写一行,代码如下:
package com.luna.base;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
public class BrAndBwAndPw {
public static void main(String[] args) throws IOException{
//对文件进行读写操作
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream("/Users/Gandoph/workspace/BasaInfo/src/file/log.dat")));
// BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
// new FileOutputStream("/Users/Gandoph/workspace/BasaInfo/src/file/log3.dat")));
PrintWriter pw = new PrintWriter("/Users/Gandoph/workspace/BasaInfo/src/file/log3.dat"); //bw替换方案
String line;
// while((line=br.readLine())!=null){
// System.out.println(line); //一次读一行,并不能识别换行
// bw.write(line);
// bw.newLine();//单独写出换行操作
// bw.flush();
// }
// br.close();
// bw.close();
while((line=br.readLine())!=null){
System.out.println(line); //一次读一行,并不能识别换行
pw.println(line);
pw.flush();
}
br.close();
pw.close();
}
}
2.对象的序列化、反序列化
1)对象的序列化就是将Object转化成byte序列,反之叫对象的反序列化;
2)序列化流(ObjectOutputStream)是过滤流——writeObject;反序列化流(ObjectInputStream)——readObject;
3)序列化接口(Serializable):对象必须实现序列化接口才能进行序列化,否则将出现异常;这个接口没有任何方法,只是一个标准;Student实例类如下:
package com.luna.base;
import java.io.Serializable;
public class Student implements Serializable{
private static final long serialVersionUID = 7446182117116524275L;
private String name;
private int age;
private transient String no; //该元素不会进行JVM默认的序列化,可以自己完成这个元素的序列化
public Student() {
super();
}
public Student(String name, Integer age, String no) {
super();
this.name = name;
this.age = age;
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", no=" + no + "]";
}
}
Student序列化反序列化类,如下所示:
package com.luna.base;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class ObjectSerialDemo {
public static void main(String[] args) throws Exception{
String file = "/Users/Gandoph/workspace/BasaInfo/src/file/log.dat";
// ObjSerial(file); //注意先执行序列化方法,后执行反序列化方法
ObjUnSerial(file);
}
public static void ObjSerial(String file) throws IOException{
//对象序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
Student stu = new Student("zhansan",20,"1001");
oos.writeObject(stu);
oos.flush();
oos.close();
System.out.println(stu);
}
public static void ObjUnSerial(String file) throws Exception{
//对象反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
Student student = (Student)ois.readObject();
System.out.println(student);
ois.close();
}
}
4)transient关键字,注意自行序列化的方法签名:
private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException
private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException
自行实现transient序列化的Student实例类,此时transient元素也可以进行序列化,如下所示:
package com.luna.base;
import java.io.Serializable;
public class Student implements Serializable{
private static final long serialVersionUID = 7446182117116524275L;
private String name;
private int age;
private transient String no; //该元素不会进行JVM默认的序列化,可以自己完成这个元素的序列化
public Student() {
super();
}
public Student(String name, Integer age, String no) {
super();
this.name = name;
this.age = age;
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", no=" + no + "]";
}
private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{
s.defaultWriteObject(); //把JVM能默认序列化的元素进行序列化操作
s.writeUTF(no); //自己完成no的序列化
}
private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject(); //把JVM能默认反序列化的元素进行反序列化操作
this.no = s.readUTF(); //自己完成no的反序列化操作
}
}
分析ArrayList源码中序列化和反序列化的问题:ArrayList不一定放满,故只序列化有效元素。
5)序列化中子类和父类构造函数的调用问题:对子类对象进行反序列化操作时,如果其父类没有实现序列化接口,那么其父类的构造函数会被调用,代码如下:
package com.luna.base;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class ObjectSerialTest {
public static void main(String[] args) throws Exception{
// serialObject();
// serialUnObject();
// serialObjectBar();
serialUnObjectBar();
}
//序列化方法Foo
public static void serialObject() throws IOException{
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("/Users/Gandoph/workspace/BasaInfo/src/file/log.dat"));
Foo2 foo2 = new Foo2();
oos.writeObject(foo2);
oos.flush();
oos.close();
}
//序列化方法Bar
public static void serialObjectBar() throws IOException{
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("/Users/Gandoph/workspace/BasaInfo/src/file/log.dat"));
Bar2 bar2 = new Bar2();
oos.writeObject(bar2);
oos.flush();
oos.close();
}
//反序列化方法:反序列化是否递归调用父类的构造方法Foo
public static void serialUnObject() throws Exception{
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("/Users/Gandoph/workspace/BasaInfo/src/file/log.dat"));
Foo2 foo2 = (Foo2)ois.readObject();
System.out.println(foo2);
ois.close();
}
//反序列化方法:反序列化是否递归调用父类的构造方法Bar
public static void serialUnObjectBar() throws Exception{
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("/Users/Gandoph/workspace/BasaInfo/src/file/log.dat"));
Bar2 bar2 = (Bar2)ois.readObject();
System.out.println(bar2);
ois.close();
}
}
/*
* 一个类实现了序列化接口,那么其子类都可以进行序列化
*/
class Foo implements Serializable{
public Foo(){
System.out.println("foo...");
}
}
class Foo1 extends Foo{
public Foo1(){
System.out.println("foo1...");
}
}
class Foo2 extends Foo1{
public Foo2(){
System.out.println("foo2...");
}
}
class Bar{
public Bar(){
System.out.println("bar...");
}
}
class Bar1 extends Bar implements Serializable{
public Bar1(){
System.out.println("bar...");
}
}
class Bar2 extends Bar1{
public Bar2(){
System.out.println("bar2...");
}
}