Java的Old IO

按操作方式分类结构图:

按操作对象分类结构图:

字节流

InputStream (Java Platform SE 7 )

OutputStream (Java Platform SE 7 )

BufferedInputStream

BufferedOutputStream

ByteArrayInputStream

ByteArrayOutputStream

DataInputStream

DataOutputStream

FileInputStream

FileOutputStream

FilterInputStream

FilterOutputStream

ObjectInputStream

ObjectOutputStream

PipedInputStream

PipedOutputStream

PrintStream

PushbackInputStream

SequenceInputStream

字符流

Reader (Java Platform SE 7 )

Writer (Java Platform SE 7 )

BufferedReader

BufferedWriter

CharArrayReader

CharArrayWriter

FileReader

FileWriter

FilterReader

FilterWriter

InputStreamReader

LineNumberReader

OutputStreamWriter

PipedReader

PipedWriter

PrintWriter

PushbackReader

StringReader

StringWriter

字节输入流

字节输出流

字符输入流

字符输出流

抽象基类

InputStream

OutputStream

Reader

Writer

访问文件

FileInputStream

FileOutputStream

FileReader

FileWriter

访问数组

ByteArrayInputStream

ByteArrayOutputStream

CharArrayReader

CharArrayWriter

访问管道(进程间通信)

PipedInputStream

PipedOutputStream

PipedReader

PipedWriter

访问字符串

StringReader

StringWriter

缓冲流(增加了缓存区,有flush方法)

BufferedInputStream

BufferdOutputStream

BufferedReader

BufferedWriter

转换流

InputStreamReader

InputStreamWriter

对象流

ObjectInputStream

ObjectOutputStream

过滤流

FilterInputStream

FilterOutputStream

FilterReader

FilterWriter

打印流

PrintStream

PrintWriter

推回输入流(带有推回缓冲区允许重复读)

PushbackInputStream

PushbackReader

特殊流

DataInputStream

DataOutputStream

Buffered Streams  https://docs.oracle.com/javase/tutorial/essential/io/buffers.html

Most of the examples we've seen so far use unbuffered I/O. This means each read or write request is handled directly by the underlying OS. This can make a program much less efficient, since each such request often triggers disk access, network activity, or some other operation that is relatively expensive.

To reduce this kind of overhead, the Java platform implements buffered I/O streams. Buffered input streams read data from a memory area known as a buffer; the native input API is called only when the buffer is empty. Similarly, buffered output streams write data to a buffer, and the native output API is called only when the buffer is full.

java.util.zip 包

CheckedInputStream

CheckedOutputStream

DeflaterOutputStream

GZIPInputStream

GZIPOutputStream

InflaterInputStream

ZipInputStream

ZipOutputStream

java.util.jar包

JarInputStream

JarOutputStream

java.security 包

DigestInputStream

DigestOutputStream

CipherInputStream

CipherOutputStream

RamdomAccessFile 可以自由访问文件的任意位置。可以读取,也可以写入

Paths

Files

FileVisitor 遍历文件和目录

WatchService 监控文件变化

对象序列化

接口Serializable(空接口Serializable (Java Platform SE 7 ))  或 Externalizable Externalizable (Java Platform SE 7 )

序列化过程:对对象序列化编号。会先查询该对象是否已经被序列化过。只有在该对象从未被序列化过,系统才会将该对象转化为自己序列并输出。如果该对象已序列化过,程序将只输出一个序列化编号。如果第一次序列化后,对象修改了,仍然只输出编号。反序列化时依旧是旧对象。

反序列化过程:不通过构造函数来初始化Java对象。读出顺序与写入顺序相同。

不需要序列化的域使用transient 修饰。

static 变量不能序列化。

当一个实现序列化接口的类有父类时,这些父类要么有无参数的构造器(这种情况下,父类的域不会被序列化),要么可以序列化,否则反序列化时将抛出InvalidClassException。

如果实现序列化接口的类内有引用类型域时,如果这种类型不是可以序列化的。那么该域也不能序列化。基本类型和String都是可以序列化的。

1.Serializable 接口

无方法

Serializable例:

class Person implements Serializable

对象输出:

ObjectInputStream oos = new ObjectOutputStream(new FileOutputSream("xxxxx"));

Person per = new Person();

oos.writeObject(per)

对象读入

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("xxxxx"))

Person per = (Person)ois.readObject()

自定义序列化方法

序列化标签方法(不输入任何接口,会通过反射调用)

private void writeObject(ObjectOutputStream out) throws IOException  自定义序列化

private void readObject(ObjectInputStream in) throws IOException,ClassNotFoundException 自定义反序列化

private void readObjectNoData() throws ObjectStreamException 如果序列化流不完整(如版本不对),反序列化会调用此方法。

更彻底的序列化标签方法,可以在序列化时将该对象替换成其他对象。

ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamExcepetion  序列化时会先调用该方法,序列化这个方法的返回值。

ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamExcepiton  该方法的返回值将会替代原来的反序列化对象,而原来的readObject()反序列化将会丢弃。

2.Externalizable 接口 完全取决于程序员

Externalizable 是 Serializable 接口的子类,通过实现的 writeExternal 和readExternal 方法,可以自己定义实现序列化和反序列化的方式;这里要注意:必须提供 public 的无参数的构造方法。

接口中两个方法

void readExternal(ObjectInput in)

void writeExternal(ObjectObject out)

两个接口对比

Serializable接口:无需代码支持,但性能略差。

Exernalizable接口:必须实现方法,但性能好。

版本

public static final long serialVersionUid=xxx;  序列化的版本。通过serialver.exe生成。

如果一个类升级后,只要它的serialVersionUID类变量不变,序列化机制就会把他们当成同一个序列化版本。如果不指定serialVersionUID,该变量的值将由JVM根据类的相关信息计算,而修改过的类计算结果与修改的类的计算结果往往不同,从而造成对象的反序列化因为类版本不一致而失败。JVM不同可能生成的版本也不同

所以随着序列化类的升级,我们可以使用 serialVersionUID 来保证升级前后的兼容性:

  • 如果希望升级前后保持兼容,那么保持 serialVersionUID 不改变;

  • 如果希望升级前后版本不兼容,那么不同版本中要设置不同的 serialVersionUID 。

  • 如果没有显式地指定 serialVersionUID ,系统会自动生成一个,而当类名、类修饰符、属性、构造器等任何一个有改变,serialVersionUID 都会变化;但是不指定 serialVersionUID 的话可能会有一些隐患,因为不同的 JVM 对于 serialVersionUID 的计算规则可能是不一样的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值