是否可以将 Process stdout InputStream 读入 NIO ByteBuffer?
是否可以使用 NIO 处理进程中的标准输出? 我让它与 java.io 一起工作,但这是一个练习,可以更多地了解 NIO 并探索性能改进的可能性。
基本上,我想在不阻塞的情况下尽快将大量文本从标准输出流式传输到缓冲区,然后稍后处理该缓冲区的内容。 问题是,我似乎无法找出正确的巫术来让它与 NIO 一起工作。 这就是我现在所处的位置:
ProcessBuilder pb = new ProcessBuilder( ... );
Process p = pb.start();
stdout = new StreamConsumer(p.getInputStream());
new Thread(stdout).start();
// other stuff omitted for brevity
StreamConsumer 类如下所示:
class StreamConsumer implements Runnable
{
private InputStream is;
public StreamConsumer(InputStream is)
{
this.is = is;
}
public void run()
{
try
{
ReadableByteChannel source = Channels.newChannel(is);
// Is it possible get a channel to a ByteBuffer
// or MappedByteBuffer here?
WritableByteChannel destination = ??;
ByteBuffer buffer = ByteBuffer.allocateDirect(128 * 1024);
while (source.read(buffer) != -1)
{
buffer.flip();
while (buffer.hasRemaining())
{
destination.write(buffer);
}
buffer.clear();
}
source.close();
destination.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
Is it possible to use NIO to process the stdout from a Process? I have it working with java.io, but this is something of an exercise to learn a bit more about NIO and to explore the possibility of performance improvements.
Basically I want to stream a large volume of text from stdout into a buffer as fast as possible without blocking, and then process the contents of that buffer later. The trouble is, I can't seem to figure out the right voodoo to make it work with NIO. This is where I am right now:
ProcessBuilder pb = new ProcessBuilder( ... );
Process p = pb.start();
stdout = new StreamConsumer(p.getInputStream());
new Thread(stdout).start();
// other stuff omitted for brevity
The class StreamConsumer looks like this:
class StreamConsumer implements Runnable
{
private InputStream is;
public StreamConsumer(InputStream is)
{
this.is = is;
}
public void run()
{
try
{
ReadableByteChannel source = Channels.newChannel(is);
// Is it possible get a channel to a ByteBuffer
// or MappedByteBuffer here?
WritableByteChannel destination = ??;
ByteBuffer buffer = ByteBuffer.allocateDirect(128 * 1024);
while (source.read(buffer) != -1)
{
buffer.flip();
while (buffer.hasRemaining())
{
destination.write(buffer);
}
buffer.clear();
}
source.close();
destination.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我创建了一个开源库,允许 java 和子进程之间的非阻塞 I/O。 该库提供了事件驱动的回调模型。 它依赖于 JNA 库来使用特定于平台的本机 API,例如 Linux 上的 epoll、MacOS X 上的 kqueue/kevent 或 Windows 上的 IO Completion Ports。
该项目名为 NuProcess,可以在此处找到:
https://github.com/brettwooldridge/NuProcess
I have created an open source library that allows non-blocking I/O between java and your child processes. The library provides an event-driven callback model. It depends on the JNA library to use platform-specific native APIs, such as epoll on Linux, kqueue/kevent on MacOS X, or IO Completion Ports on Windows.
The project is called NuProcess and can be found here:
https://github.com/brettwooldridge/NuProcess
不管你相信与否,我认为你想要的可写字节通道是
然后当完成时
包含要处理的字节。 或者,如果您想要一个字节缓冲区,
我在这里看不到如何在可运行对象之外获取输出,但我怀疑您的原始代码具有该缓冲区。 否则,您可能希望 StreamConsumer 成为 Callable。
Believe it or not, I think the writable byte channel you want is
Then when done
contains the bytes to process. Or, if you want a byte buffer,
I don't see here how you get the output outside the runnable, but I suspect your original code had that. Otherwise you might want the
StreamConsumer
to be aCallable<ByteBuffer>
.另一个可以尝试的非阻塞选项可能是使用 Guava 的 ListenableFuture 为您提供成功和失败回调,而无需解释您自己的错误。
Another non blocking option to try might be to use Guava's ListenableFuture giving you success and failure callbacks without interpreting errors of your own.