【问题标题】:What happens when I wrap I/O streams twice?当我两次包装 I/O 流时会发生什么?
【发布时间】:2014-08-20 05:34:52
【问题描述】:

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

请澄清两个代码sn-ps之间的区别:

sn-p 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());

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

sn-p 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());

这段代码只是挂断了。我不明白为什么。请澄清。

附言

这只是理论问题。

更新

由于我使用管道(根据 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());

【问题讨论】:

  • 我怀疑这是否可以正常工作并且流已损坏。

标签: java io stream wrapper decorator


【解决方案1】:

您在滥用管道流。它们旨在供执行写入的生产者线程和执行读取的消费者线程使用。请参阅 Javadoc。

管道流共享一个缓冲区,如果读取线程不读取,则可以填充该缓冲区,这会使您的写入线程停止。

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

【讨论】:

  • 在管道 Java 文档中写下可能的死锁
  • 我更新了主题。你能回答选题吗?
【解决方案2】:
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());

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-19
    • 1970-01-01
    • 2010-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-05
    相关资源
    最近更新 更多