OutputStream直接写入我的字节块列表

时间:2016-09-20 08:01:36

标签: java stream outputstream

我有一个库,可以生成PDF文档并将其写入OutputStreamOutputStream传递给PDF库。我需要将结果数据存储在 List<Byte[]> List<byte[]>中,每个条目的固定长度为255个字节。 (我无法改变有关此要求的任何内容,请参阅评论中的更多内容。)

现在最简单的解决方案是使用ByteArrayOutputStream并将生成的字节数组写入(并反汇编)到字节数组列表中。

但我想要一个更有效的解决方案,需要更少的内存。我希望输出流直接生成字节数组列表。

我的解决方案是扩展OutputStream,覆盖write()并将数据直接写入List<byte[]>

这需要一些努力(例如跟踪已经收到的字节数),因此我想知道,如果使用其他可用的OutputStream实现有更简单的解决方案。

E.g。我想过以某种方式使用BufferedOutputStream,但我认为这不会起作用。基本思想是实现另一个OutputStream,将其传递给具有255字节容量的BufferedOutputStream并写入一个新的块条目,每次BufferdOutputStream刷新其缓冲区时它都已满。我认为这不起作用,因为BufferedOutputStream如果一次写入太多字节就不再使用它的缓冲区(据我所知,它的源代码)。

1 个答案:

答案 0 :(得分:0)

这是我在问题中提出的快速实施方式。但是,它没有经过测试。但是在我的代码中使用它之前我必须做一些具体的更改,并且在应用这些更改之前我会分享它。

public class ByteArrayListGeneratingOutputStream extends OutputStream
{
   private byte[] buf;
   private int off = 0;
   private int size;
   private List<byte[]> result = new ArrayList<byte[]>();

   public ByteArrayListGeneratingOutputStream(int size)
   {
      this.size = size;
      buf = new byte[size];
   }

   public List<byte[]> getResult()
   {
      return result;
   }

   @Override
   public void write(int b) throws IOException
   {
      allocateBufferIfNeeded();
      buf[off++] = (byte) b;
      flushBufferIfNeeded();
   }

   @Override
   public void write(byte buf[], int off, int len) throws IOException
   {
      if ((off < 0) || (off > buf.length) || (len < 0) || ((off + len) > buf.length) || ((off + len) < 0))
      {
         throw new IndexOutOfBoundsException();
      }
      while (len > 0)
      {
         allocateBufferIfNeeded();
         int effectiveLen = Math.min(len, size - this.off);
         System.arraycopy(buf, off, this.buf, this.off, effectiveLen);
         this.off += effectiveLen;
         off += effectiveLen;
         len -= effectiveLen;
         flushBufferIfNeeded();
      }
   }

   private void flushBufferIfNeeded() throws IOException
   {
      if (off == size)
      {
         flush();
      }
   }

   private void allocateBufferIfNeeded()
   {
      if (buf == null)
      {
         buf = new byte[size];
         off = 0;
      }
   }

   @Override
   public void flush() throws IOException
   {
      if (off > 0)
      {
         result.add(buf);
         off = 0;
         buf = null;
      }
   }

   @Override
   public void close() throws IOException
   {
      flush();
   }
}