【问题标题】:Using OutputStream with multiple ObjectOutputStreams?将 OutputStream 与多个 ObjectOutputStream 一起使用?
【发布时间】:2017-01-01 16:05:56
【问题描述】:

为了从特定的序列化格式中抽象出来,我想定义以下内容:

public interface TransportCodec {
  void write(OutputStream out, Object obj) throws IOException;      
  Object read(InputStream in) throws IOException;
}

默认实现会像这样使用 Java 对象序列化:

public void write(OutputStream out, Object obj) throws IOException {
  ObjectOutputStream oout = new ObjectOutputStream(out);
  oout.writeObject(obj);
  oout.flush();
}

显然oout.close() 丢失了,但有一个原因:我希望能够通过独立调用write 将多个对象写入同一个流。查看ObjectOutputStream(jdk 1.8)的源代码,oout.close() 关闭了底层流,但也清除了属于ObjectOutputStream 的数据结构。但是由于我将oout 留给了垃圾收集器,所以我不会期望不关闭流会出现问题。

除了未来的 JDK 确实需要oout.close() 的风险之外,还有两个问题:

  1. 如果不关闭上面的ObjectOutputStream,我在当前的 JDK 中会丢失什么。
  2. 首先序列化为ByteArrayOutputStream,然后将字节复制到out 将允许关闭oout。有更好的选择吗?

【问题讨论】:

    标签: java serialization objectoutputstream


    【解决方案1】:

    分成两个接口,让实现类“拥有”底层流。

    优点:

    • 基础存储不再局限于OutputStream/InputStream

    • 通过使这两个接口扩展Closeable,它们现在可以在try-with-resources 块中使用。

    • 调用者只需要携带一个引用(例如TransportEncoder),并且不再需要携带流(例如OutputStream)。

    接口

    public interface TransportEncoder extends Closeable {
        void write(Object obj) throws IOException;
    }
    public interface TransportDecoder extends Closeable {
        Object read() throws IOException;
    }
    

    ObjectStream 实现

    public final class ObjectStreamEncoder implements TransportEncoder {
        private final ObjectOutputStream stream;
        public ObjectStreamEncoder(OutputStream out) throws IOException {
            this.stream = new ObjectOutputStream(out);
        }
        @Override
        public void write(Object obj) throws IOException {
            this.stream.writeObject(obj);
        }
        @Override
        public void close() throws IOException {
            this.stream.close();
        }
    }
    public final class ObjectStreamDecoder implements TransportDecoder {
        private final ObjectInputStream stream;
        public ObjectStreamDecoder(InputStream in) throws IOException {
            this.stream = new ObjectInputStream(in);
        }
        @Override
        public Object read() throws IOException {
            try {
                return this.stream.readObject();
            } catch (ClassNotFoundException e) {
                throw new NoClassDefFoundError(e.getMessage());
            }
        }
        @Override
        public void close() throws IOException {
            this.stream.close();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-05-21
      • 1970-01-01
      • 2012-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多