一、流
从文件、网络、内存块中 读入一个字节序列(输入流),写入一个字节序列(输出流)。抽象类 InputStream和 OutputStream构成了输入和输出类层次结构的基础。
字符和字节的区别:字符有自己的编码规则,一个字符可能由很多个字节组成。
流是面向字节的,所以不太适合处理以字符形式存储的信息。Java从Reader和Writer抽象类中派生出了一个单独的类层次结构,专门用于处理Unicode码元。
Java拥有一个庞大的流家族,InputStream和 OutputStream可以进行 字节或者字节数组的读写。如果想要进行例如文件读写之类的操作,就需要依赖于其 实现了更多功能的子类:FileInputStream、FileOutputStream可以对文件进行读写,DataInputStream和DataOutputStream可以以 二进制的形式读写所有的基本Java类型。
二、流的组合
Java中流的功能是很单一的,当我们使用FileInputStream时,就只能从 文件中获取二进制流,而此时 如果我们还希望从中读取数值类型的话,需要将文件流继续传递给 DataInputStream,来进行 数值类型的读取。
在Java中,可以通过组合几种 Stream来 达到我们想要的功能。例如:流在默认情况下,是不被缓冲区缓存的,也就是说,每次read操作,都需要操作系统分发一个字节,相比之下,一次请求一个数据块,然后将其缓存起来会高效很多。此时,就需要先使用 FileInputStream先从文件中读取流,然后将其 传入 BufferedInputStream中,以使用缓冲机制,最后 将其传入DataInputStream中,以读取其中的数值结果。
三、文本输入、输出
可以使用 PrintWriter类进行文本输出,这个类拥有 以文本方式打印字符串和数字的方法,甚至还有一个输出到文件的快捷方式。
可以使用 Scanner类以文本格式读入数据。
四、对象流和序列化
Java支持一种通用的机制:对象序列化。使用ObjectOutputStream将对象写入流中,然后再 使用 ObjectOuputStream读取出来。当然,需要进行序列化的类 应当 实现 Serializable接口,此为标记接口,表示这个类可以进行序列化。
对象序列化的基本算法:
1、每个对象引用都关联一个序列号 2、对于每个对象,当 第一次遇到时,将其保存到流中 3、如果某个对象之前已经遇到过,则只保存其序列号
可以使用 序列化机制来 实现深拷贝:
public class SerialCloneable implements Serializable, Cloneable{
@Override
public Object clone(){
try {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(bout);
objectOutputStream.writeObject(this);
objectOutputStream.close();
ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(bout.toByteArray()));
Object object = objectInputStream.readObject();
objectInputStream.close();
return object;
}catch (Exception e){
return null;
}
}
}
任意类只要继承自这个类 便可以实现深拷贝。可以通过 打印对象的内存地址发现克隆前后的是 不同的对象。