一. 转换流
InputStreamReader/OutputStreamWriter用来实现将字节流转化成字符流。
举一个实例:
System.in是字节流对象,代表键盘的输入; 而System.out也是字节流对象,代表输出到显示器。现在我们将这两个字节流对象转换成字符流。
package cn.zjb.test;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
/**
* 测试转换流
* @author 张坚波
*
*/
public class TestTransformStream {
public static void main(String[] args) {
BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); //可用缓冲流进行包装
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
String str=null;
try { //看别人都说try-catch规范,以后就这么写
while(!"quit".equals(str=br.readLine())) { //避免空指针异常的规范
bw.write(str);
bw.newLine();
bw.flush(); //必须手动刷新
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(br!=null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bw!=null) {
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
运行结果:
其实IO这一章,自我感觉学的不是很透彻,因为有很多问题在原理上没有得到解决。就拿这个flush()方法,网上都只是以比喻的形式做说明,确实很好理解,但没有从本质上说明,这就是隐患啊。虽然代码都是自己敲的,但是总感觉很迷糊的样子,就只是会敲代码远远不够啊。 因此买了本教材,马上就到了,希望可以帮我解决一些问题,到时候把IO全部按照正确思路再走一遍。
二. 对象流
我们前边学到的数据流只能实现对基本数据类型和字符串类型的读写,并不能读取对象(字符串除外),如果要对某个对象进行读写操作,我们需要学习一对新的处理流:ObjectInputStream/ObjectOutputStream。
ObjectInputStream/ObjectOutputStream是以“对象”为数据源,但是必须将传输的对象进行序列化与反序列化操作。
把Java对象转换为字节序列的过程称为对象的序列化。把字节序列恢复为Java对象的过程称为对象的反序列化。这两个过程知道就行,在具体使用的时候是不用自己实现的。但是要注意的一点是: 只有实现了Serializable接口的类的对象才能被序列化。Serializable接口是一个空接口,只起到标记作用。
现在我以 object (对象输出流) --> (文件输出流) file (文件输入流) --> (对象输入流) object 的方式编写一下代码:
package cn.zjb.test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* 测试对象流
* @author 张坚波
*
*/
public class TestObjectStream {
public static void main(String[] args) {
Boys boy=new Boys("小张");
ObjectOutputStream oos=null;
ObjectInputStream ois=null;
try {
oos=new ObjectOutputStream( new FileOutputStream("srcfile"));
oos.writeObject(boy);
oos.flush();
ois=new ObjectInputStream( new FileInputStream("srcfile"));
Object instance=ois.readObject();
System.out.println(instance);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(ois!=null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(oos!=null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
class Boys implements java.io.Serializable{
//添加序列化ID
private static final long serialVersionUID = 1L;
private String name;
public Boys(String name) {
this.name=name;
}
@Override
public String toString() {
return name+"\n" +
"总喜欢在大街上站立\n" +
"把等的那个家伙放在心底\n" +
"因为这是个秘密\n" ;
}
}
运行结果:
出现了乱码?一定是解码字符集的问题。换了也没用。。这个问题就不清楚了。。。
要是小张比较害羞,不愿意透露自己的名字,我们怎么办呢?可以使用transient关键字,使这个信息不公开:private transient String name;
就变成这样啦!
最后有几点注意事项:
- static属性不参与序列化。
- 对象中的某些属性如果不想被序列化,不能使用static,而是使用transient修饰。
- 为了防止读和写的序列化ID不一致,一般指定一个固定的序列化ID。
晚上还上了节网课,有点赶,等书到了IO是肯定要重来的,也不急。