2016-09-20 27 views
0

我有一个库生成PDF文档并将其写入OutputStreamOutputStream被传递给PDF库。我需要将结果数据存储在每个条目具有255字节的固定长度的List<byte[]>中。 (我不能改变任何关于这个要求的内容,在评论中可以看到更多内容。)直接写入我的字节块列表的OutputStream

现在最简单的解决方案是使用ByteArrayOutputStream并将结果字节数组写入(和拆分)到字节数组列表中。

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

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

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

E.g.不知何故,我想过使用BufferedOutputStream,但我认为这是行不通的。基本思路是实现另一个OutputStream,将它传递给BufferedOutputStream,容量为255字节,并写入一个新的块条目,每次BufferdOutputStream在缓冲区满时都将其刷新。我认为这不起作用,因为BufferedOutputStream不再使用它的缓冲区了,如果一次写入太多的字节(据我了解它的源代码)。

+0

为什么不做'List '? – Shadov

+0

定义'期望一个255字节块的列表'。不清楚你在问什么。 – EJP

+0

@EJP一个'列表',每个'Byte []'条目的长度为255.(最后一个条目可以少于255个字节)。 @Whatzs是的,如果与目标服务器通信的框架不期望后者,我可以使用'byte []'而不是'Byte []'。 – fishbone

回答

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(); 
    } 
} 
相关问题