Op *_*kel 4 java io object-design
在他们的公共API中有许多java标准和第三方库,有写入或读取的方法Stream.一个例子是javax.imageio.ImageIO.write()将OutputStream处理过的图像的内容写入其中.另一个例子是iText pdf处理库,它将OutputStream生成的pdf写入其中.第三个例子是AmazonS3 Java API,InputStream它将读取它并在S3存储中创建文件.
当你想要结合其中两个时,问题就会出现问题.例如,我有一个图像BufferedImage,我必须用它ImageIO.write来推动结果OutputStream.但是,正如S3所要求的那样,没有直接的方法将其推送到Amazon S3 InputStream.
有很多方法可以解决这个问题,但这个问题的主题是使用ByteArrayOutputStream.
后面的想法ByteArrayOutputStream是使用一个包含在其中的中间字节数组,Input/Output Stream以便想要写入输出流的人将写入数组并且想要读取的人将读取数组.
我不知道为什么ByteArrayOutputStream不复制它就不允许任何对字节数组的访问,例如,提供一个InputStream可以直接访问它的字节数组.访问它的唯一方法是调用toByteArray(),它将复制内部数组(标准数组).这意味着,在我的图片示例中,我将在内存中拥有三个图像副本:
BufferedImage,array的OutputStream并toByteArray()我制作的副本,所以我可以创建
InputStream.这个设计如何合理?
getInputStream(),实施保持隐藏. ByteArrayOutputStream不管怎样都不适合多线程访问,所以这不可能. 此外,ByteArrayOutputStreamApache的commons-io库(具有不同的内部实现)提供了第二种风格.但两者都具有完全相同的公共接口,无法在不复制的情况下访问字节数组.
我想知道为什么ByteArrayOutputStream不允许任何访问字节数组而不应对它,例如,提供一个可直接访问它的InputStream.
我可以想到四个原因:
当前实现使用单字节数组,但它也可以实现为字节数组的链接列表,推迟创建最终数组,直到应用程序请求它为止.如果应用程序可以看到实际的字节缓冲区,则它必须是单个数组.
相反,你的理解ByteArrayOutputStream 是线程安全的,并且是适用于多线程应用.但是,如果直接访问字节数组,很难看出如何在不产生其他问题的情况下同步.
API需要更复杂,因为应用程序还需要知道当前缓冲区高水位线的位置,以及字节数组是否(仍然是)实时字节数组.(ByteArrayOutputStream实现偶尔需要重新分配字节数组......这将使应用程序保持对不再是数组的数组的引用.)
当您公开字节数组时,您允许应用程序修改数组的内容,这可能会有问题.
这个设计如何合理?
该设计专为比您更简单的用例而量身定制.Java SE类库不旨在支持所有可能的用例.但它们不会阻止您(或第三方库)为其他用例提供其他流类.
最重要的是,太阳设计师决定不公开字节数组ByteArrayOutputStream,而且(IMO)你不太可能改变他们的想法.
(如果你想尝试,这不是正确的地方.
如果您能够提出一个不太危险的API设计,那么您可能会更成功地说服Apache Commons IO开发人员了解您论证的正确性.
或者,没有什么能阻止您实现自己的特殊用途版本,从而暴露其内部数据结构.代码是GPL,因此您可以复制它...遵循有关代码分发的正常GPL规则.