java.io中用于装饰流的限制是什么?

时间:2014-06-30 20:28:06

标签: java serialization io stream decorator

我想象这样的装饰模式: enter image description here

我知道java io使用这种模式。

我觉得对包装对象存在一些限制,但我无法理解整个规则。

研究代码:

摘录1 - 工作代码:

    OutputStream outputStream = new FileOutputStream("2.txt");

    ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
    ObjectOutputStream objectOutputStreamWrapper = new ObjectOutputStream(objectOutputStream);     //double wrapping

    objectOutputStreamWrapper.writeObject("this is my string");
    objectOutputStreamWrapper.close();

    ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("2.txt"));
    ObjectInputStream   objectInputStreamWrapper = new ObjectInputStream(objectInputStream);


    System.out.println(objectInputStreamWrapper.readObject());
    objectInputStream.close();

代码段2 - 无法正常工作:

    OutputStream outputStream = new FileOutputStream("2.txt");

    ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
    ObjectOutputStream objectOutputStreamWrapper = new ObjectOutputStream(objectOutputStream);     //double wrapping

    objectOutputStreamWrapper.writeObject("this is my string");
    objectOutputStreamWrapper.close();

    ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("2.txt"));
    //ObjectInputStream   objectInputStreamWrapper = new ObjectInputStream(objectInputStream);


    System.out.println(objectInputStream.readObject());
    objectInputStream.close();

输出:

Exception in thread "main" java.io.OptionalDataException
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1361)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
    at io.WrappingUnwrappingOrderingTest.main(WrappingUnwrappingOrderingTest.java:28)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

摘录3 - 无效

    OutputStream outputStream = new FileOutputStream("2.txt");

    ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
  //  ObjectOutputStream objectOutputStreamWrapper = new ObjectOutputStream(objectOutputStream);     //double wrapping

    objectOutputStream.writeObject("this is my string");
    objectOutputStream.close();

    ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("2.txt"));
    ObjectInputStream   objectInputStreamWrapper = new ObjectInputStream(objectInputStream);


    System.out.println(objectInputStreamWrapper.readObject());
    objectInputStream.close();

输出:

Exception in thread "main" java.io.EOFException
    at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2325)
    at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:2794)
    at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:801)
    at java.io.ObjectInputStream.<init>(ObjectInputStream.java:299)
    at io.WrappingUnwrappingOrderingTest.main(WrappingUnwrappingOrderingTest.java:25)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

看起来文件系统中的文件存储有关流装饰顺序的信息。对我来说很奇怪。请澄清这个误解。

我总是应该使用严格相同的装饰器顺序进行输入和输出吗?

1 个答案:

答案 0 :(得分:3)

这里的问题是constructing an ObjectOutputStream将一些字节写入基础流:

  

创建一个写入指定OutputStream的ObjectOutputStream。此构造函数将序列化流标头写入基础流

同样,创建ObjectInputStream会读取序列化头。

因此,如果你打开两个ObjectOutputStream并只使用一个读取,反之亦然,你将不会读取尽可能多的序列化头文件,导致它无法工作,如堆栈跟踪所示:

  

at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:801)

这是ObjectOutputStream非常独特的东西。例如,将缓冲流包装到缓冲流中不会出现此问题。