【发布时间】:2015-05-30 22:47:43
【问题描述】:
我有一个组件在输出流 (ByteArrayOutputStream) 中为我提供数据,我需要将其写入 SQL 数据库的 blob 字段而不创建临时缓冲区,因此需要获取输入流。
根据here 和here 的回答,我想出了以下方法从输出流中获取输入流:
private PipedInputStream getInputStream(ByteArrayOutputStream outputStream) throws InterruptedException
{
PipedInputStream pipedInStream = new PipedInputStream();
Thread copyThread = new Thread(new CopyStreamHelper(outputStream, pipedInStream));
copyThread.start();
// Wait for copy to complete
copyThread.join();
return pipedInStream;
}
class CopyStreamHelper implements Runnable
{
private ByteArrayOutputStream outStream;
private PipedInputStream pipedInStream;
public CopyStreamHelper (ByteArrayOutputStream _outStream, PipedInputStream _pipedInStream)
{
outStream = _outStream;
pipedInStream = _pipedInStream;
}
public void run()
{
PipedOutputStream pipedOutStream = null;
try
{
// write the original OutputStream to the PipedOutputStream
pipedOutStream = new PipedOutputStream(pipedInStream);
outStream.writeTo(pipedOutStream);
}
catch (IOException e)
{
// logging and exception handling should go here
}
finally
{
IOUtils.closeQuietly(pipedOutStream);
}
}
}
请注意,输出流已经包含写入的数据,它最多可以运行 1-2 MB。
然而,无论尝试在两个单独的线程或同一个线程中执行此操作,我发现总是PipedInputStream 挂在以下位置:
Object.wait(long) line: not available [native method]
PipedInputStream.awaitSpace() line: not available
【问题讨论】:
-
组件应该返回一个 InputStream。 OutputStream 是一个接收器,并不意味着被读取。在这种情况下,这是可能的,因为 ByteArrayOutputStream 的特殊性质。您避免临时缓冲区的目标会丢失,因为 ByteArrayOutputStream 在传递时已经包含完整数据。
-
@Sponiro,同意,但我想防止创建另一个缓冲区只是为了获取输入流。所述组件生成输出,所以我不清楚它如何返回 InputStream?
-
一个简单的解决方案是先将数据写入文件,然后打开 InputStream 进行读取。如果您真的想将 PipedInputStream 用于真正的生产者-消费者场景,则需要使用两个线程。这是完全可能的,但有点复杂。您的组件将存在于一个线程中并分发一个 InputStream(实际上是一个 PipedInputStream),另一个线程将选择那个并从中读取。您上面的解决方案创建了一个线程并等待其结果,这是非常不同的。
-
@Sponiro,我考虑并放弃了写入文件,因为我认为这是不必要的。我在这里所拥有的不是通常意义上的生产者-消费者场景,两者都可以异步发生。这里的情况是组件已完成输出并将数据写入 OutputStream。现在我需要获取该数据并通过 SQL 语句将其发送到数据库。鉴于此,我试图找到最有效的方法。从看起来这可能是不可能的 - 这意味着链接的 SO 问题上的其他类似答案不起作用?
-
@Sponiro,继续...关于需要两个线程才能使管道流正常工作,我上面显示的代码 正在 这样做 - 你看到了什么错了,因为它没有按我的预期工作。
标签: java inputstream outputstream