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..."); } }