javaI/O库的设计原理:第七课 E 11097
·java io库提供了一种被称为链接的机制,可以将一个流和另一个流收尾相接,形成一个流的管道链接。这种机制实际就是被称为Decorator(装饰)设计模式的应用。
·通过流的链接,可以动态增加流的功能。而这种功能是通过组合一些基本流功能而动态获取的
·我们要获取一个io对象,往往需要产生多个对象,这也是io库不太容易掌握的原因。但Decorator设计模式的应用为我们提供了实现上的灵活性 。
前面为大家介绍的流类,都是对字节流进行操作,但有时需要用到字符流。这时我们就可以使用java为我们提供的Reader和Writer这两个类。这两个类是用来对字符流进行操作。(java使用Unicode来表示字符和字符串)
import java.io.*;
class ReaderWriterStreamTest
{
public static void main(String[] args) throws Exception
{
FileOutputStream fos = new FileOutputStream("88.txt");
//OutputStreamWriter 是字符流通向字节流的桥梁
//注意,传递到此 write() 方法的字符是未缓冲的。 为了达到最高效率,可考
//虑将OutputStreamWriter包装到BufferedWriter中以避免频繁调用转换器。例:
//Writer out = new BufferedWriter(new OutputStreamWriter(System.out));
OutputStreamWriter osw = new OutputStreamWriter(fos); //很少使用OutputStreamWriter类来进行写入操作
BufferedWriter bw =new BufferedWriter(osw); //BufferedWriter对象来完成写入操作效率更高
bw.write("hello: ReaderWriterStream");
bw.close();
FileInputStream fis = new FileInputStream("88.txt");
InputStreamReader isr = new InputStreamReader(fis); //定义一个InputStreamReader对象作为字节流到字符流转换的桥梁
BufferedReader br =new BufferedReader(isr);
String str = br.readLine(); //读取一行数据,如果多行,可循环此方法 如果已到达流末尾,则返回 null
System.out.println(str);
}
}
我们也可以在标准的输入输出控制台中来实现读取和写入操作:
import java.io.*;
class ReaderWriterStreamTest
{
public static void main(String[] args) throws Exception
{
InputStreamReader isr = new InputStreamReader(System.in);//利用System.in创建标准的输入流对象
BufferedReader br =new BufferedReader(isr);
String str = br.readLine();
if(str!=null)
{
System.out.println(str);
}
br.close();
}
}
RandomAccessFile 第七课H 7328
RandomAccessFile类同时实现了DataInput接口和DateOutput接口,利用这个类可以实现在文件任何位置进行读或写操作。同时提供了文件指针,用来表示将要读写的下一位数据的位置。
对象序列化(反串) 第七课I 6538
将对象转换为字节流保存起来,并在日后还原这个对象,这种机制叫做对象序列化。
一个对象要实现序列化,就必须实现Serializable接口和Externalizable接口。Serilizable接口中无任何方法,Externalizable接口由Serializable接口(无任何抽象方法)继承而来,
实现一个对象序列化可以使用ObjectOutputstream和ObjectInputStream这两个类。
import java.io.*;
class ObjectSerialTest
{
public static void main(String[] args) throws Exception
{
Employee e1 =new Employee("zhangshan",26,5000);
Employee e2 =new Employee("lisi",36,3000);
Employee e3 =new Employee("wangwu",46,4000);
//实现对象序列化
FileOutputStream fos = new FileOutputStream("employee.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(e1);
oos.writeObject(e2);
oos.writeObject(e3);
oos.close();
//实现对象饭序列化
//下面定义一个对象输入流,用于读取上面定义的3个雇员对象的资料
FileInputStream fis = new FileInputStream("employee.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
Employee e;
for(int i=0;i<3;i++)
{
e=(Employee)ois.readObject();
System.out.println("name:"+e.name+"/n age:"+e.age+"/n salary:"+e.salary);
}
}
}
class Employee implements Serializable
{
String name;
int age;
double salary;
Employee(String name, int age,double salary)
{
this.name=name;
this.age=age;
this.salary=salary;
}
}
但是注意:当序列化一个对象时,只能保存对象的非静态成员变量,不能保存任何成员方法和静态成员变量。如果一个对象的成员变量是一个对象,那么这个对象的数据额也会被保存。
如果一个可序列化的对象包含一个不可序列化的对象引用,那么这个对象序列化操作将失败,并抛出NotSerializableException,我们可以将这个不可序列化对象引用标记为transient,那么对象任然可以序列化。例如我们将上例中的Employee类改为:
class Employee implements Serializable
{
String name;
int age;
double salary;
Thread th = new Thread();
Employee(String name, int age,double salary)
{
this.name=name;
this.age=age;
this.salary=salary;
}
}
这时再运行java ObjectSerialTest 就会抛出NotSerializableException,如果需要继续正常序列化,需要改为:
transient Thread th = new Thread();