当我将I / O流包装两次时会发生什么?

时间:2014-06-29 20:44:02

标签: java io stream wrapper decorator

我知道java I / O使用装饰器模式。但我觉得我理解它错了。

请澄清两个代码段之间的区别:

代码段1:

    PipedInputStream pipedInputStream = new PipedInputStream();
    PipedOutputStream pipedOutputStream = new PipedOutputStream();
    pipedOutputStream.connect(pipedInputStream);


    ObjectOutputStream objectOutputStream = new ObjectOutputStream(pipedOutputStream);

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

    ObjectInputStream objectInputStream = new ObjectInputStream(pipedInputStream);

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

此应用程序按照我的预期工作,我在控制台中看到结果。

代码段2:

我尝试将ObjectInputStream和ObjectOutputStream包装两次:

        PipedInputStream pipedInputStream = new PipedInputStream();
        PipedOutputStream pipedOutputStream = new PipedOutputStream();
        pipedOutputStream.connect(pipedInputStream);


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

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

        ObjectInputStream objectInputStream = new ObjectInputStream(pipedInputStream);
        ObjectInputStream   objectInputStreamWrapper = new ObjectInputStream(objectInputStream);

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

此代码暂停。我不明白为什么。请澄清。

P.S。

这只是理论问题。

更新

因为我使用管道而真的挂起了行为(根据EJP回答)。

例如,这段代码符合预期。

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

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

            objectOutputStreamWrapper.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();

看起来如果我用10个装饰器包装输入,我应该以相同的顺序包装10个装饰器的输出。这是真的吗?

更新+ 1

我注意到只有刷新的问题:

PipedInputStream pipedInputStream = new PipedInputStream();
    PipedOutputStream pipedOutputStream = new PipedOutputStream();
    pipedOutputStream.connect(pipedInputStream);


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

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

    objectOutputStreamWrapper.flush();

    ObjectInputStream objectInputStream = new ObjectInputStream(pipedInputStream);
    ObjectInputStream   objectInputStreamWrapper = new ObjectInputStream(objectInputStream);

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

2 个答案:

答案 0 :(得分:1)

您滥用管道流。它们旨在由执行写入的生产者线程和执行读取的使用者线程使用。见Javadoc。

管道流共享一个缓冲区,如果读取线程没有读取,它可以填充,这会拖延你的写作线程。

两次包装流并没有任何关系,尽管在这种情况下它肯定是没有意义和有问题的。

答案 1 :(得分:0)

PipedInputStream pipedInputStream = new PipedInputStream();
PipedOutputStream pipedOutputStream = new PipedOutputStream();
pipedOutputStream.connect(pipedInputStream);
//writing 
ObjectOutputStream objectOutputStream = new ObjectOutputStream(pipedOutputStream);
//ObjectOutputStream objectOutputStreamWrapper =new ObjectOutputStream(objectOutputStream);
//ObjectOutputStream objectOutputStreamWrapper1=new ObjectOutputStream(objectOutputStreamWrapper);
//objectOutputStreamWrapper1.writeObject("this is my string");
//objectOutputStreamWrapper1.flush();
objectOutputStream.writeObject("this is my string");
//reading 
ObjectInputStream objectInputStream = new ObjectInputStream(pipedInputStream);
//ObjectInputStream objectInputStreamWrapper = new ObjectInputStream(objectInputStream);
//ObjectInputStream objectInputStreamWrapper1=new ObjectInputStream(objectInputStreamWrapper);
//System.out.println("going to read from piped source");
//System.out.println(objectInputStreamWrapper1.readObject());
System.out.println(objectInputStream.readObject());

Snippet 1 - 使用Piped流创建的OutputStream,然后输入流直接通过缓冲区从管道接收数据而不刷新。

更新+ 1 - 使用outputstream包装器创建的OutputStream依次使用另一个包装器(注释包装器语句)等等,在flush语句之后工作。 Flush explicitlty将缓冲的数据刷新到底层流,在我们的例子中是管道输出流或输出流。

可以像使用FilterOutputStream一样使用嵌套流,也可以在ObjectOutputStream之上使用。