0

我的计划是使用ByteBufferApache Common Exec将一个命令的输出作为输入发送到另一个命令。

我可以使用PipedOutputStreamand来做到这一点PipedInputStream,下面是可以正常工作的代码。

public static void testApacheCommons1() throws ExecuteException, IOException {
        PipedOutputStream ifOutputStream = new PipedOutputStream();
        PipedInputStream ifInputStream = new PipedInputStream();
        ifOutputStream.connect(ifInputStream);

        String readCommand = "sudo dd bs=1 count=30 if=" + "/dev/sdb1" + " skip=50k";
        CommandLine cmdLineForRead = CommandLine.parse(readCommand);
        DefaultExecutor executorRead = new DefaultExecutor();
        ExecuteStreamHandler executeReadStreamHandler = new PumpStreamHandler(ifOutputStream);
        executorRead.setStreamHandler(executeReadStreamHandler);
        executorRead.execute(cmdLineForRead, new DefaultExecuteResultHandler());

        String writeCommand = "sudo dd bs=1 of=" + "/dev/sdb2"+ " seek=50k";
        CommandLine cmdLineForWrite = CommandLine.parse(writeCommand);
        DefaultExecutor executorWrite = new DefaultExecutor();
        ExecuteStreamHandler executeWriteStreamHandler = new PumpStreamHandler(System.out, System.err, ifInputStream);
        executorWrite.setStreamHandler(executeWriteStreamHandler);
        executeWriteStreamHandler.start();
        executorWrite.execute(cmdLineForWrite, new DefaultExecuteResultHandler());
    }

上面的代码工作正常,但我想从第一个命令中获取输出,并将其放入ByteBuffer 并提供它作为下一个命令的输入。

下面是我正在尝试执行的代码,但它没有按预期工作(我能够看到缓冲区被填充,但它没有写入磁盘,当我使用PipedOutputStreamand时发生在上面的代码中PipedInputStream)。

在这种情况下,我使用ByteBufferBackedOutputStreamByteBufferBackedInputStream是自定义类,我从 SO 的另一篇文章中获得了实现。

public static void testApacheCommons() throws ExecuteException, IOException {

        ByteBuffer byteBuffer = ByteBuffer.allocate(30);

        String readCommand = "sudo dd bs=1 count=30 if=" + "/dev/sdb1" + " skip=50k";
        CommandLine cmdLineForRead = CommandLine.parse(readCommand);
        DefaultExecutor executorRead = new DefaultExecutor();
        ExecuteStreamHandler executeReadStreamHandler = new PumpStreamHandler(
                new ByteBufferBackedOutputStream(byteBuffer));
        executorRead.setStreamHandler(executeReadStreamHandler);
        executorRead.execute(cmdLineForRead, new DefaultExecuteResultHandler());

        String writeCommand = "sudo dd bs=1 of=" + "/dev/sdb2" + " seek=50k";
        CommandLine cmdLineForWrite = CommandLine.parse(writeCommand);

        DefaultExecutor executorWrite = new DefaultExecutor();
        ExecuteStreamHandler executeWriteStreamHandler = new PumpStreamHandler(System.out, System.err,
                new ByteBufferBackedInputStream(byteBuffer));
        executorWrite.setStreamHandler(executeWriteStreamHandler);
        executorWrite.execute(cmdLineForWrite, new DefaultExecuteResultHandler());

    }

public class ByteBufferBackedInputStream extends InputStream {

    ByteBuffer buf;

    public ByteBufferBackedInputStream(ByteBuffer buf) {
        this.buf = buf;
    }

    public int read() throws IOException {
        if (!buf.hasRemaining()) {
            return -1;
        }
        return buf.get() & 0xFF;
    }

    public int read(byte[] bytes, int off, int len) throws IOException {
        if (!buf.hasRemaining()) {
            return -1;
        }

        len = Math.min(len, buf.remaining());
        buf.get(bytes, off, len);
        return len;
    }
}



public class ByteBufferBackedOutputStream extends OutputStream {
    ByteBuffer buf;

    public ByteBufferBackedOutputStream(ByteBuffer buf) {
        this.buf = buf;
    }

    public void write(int b) throws IOException {
        buf.put((byte) b);
    }

    public void write(byte[] bytes, int off, int len) throws IOException {
        buf.put(bytes, off, len);
    }

}
4

1 回答 1

0

好的,问题是positionforbytebuffer位于最后一个位置,因此当写入发生时,它没有找到保存在缓冲区中的元素。通过跟踪和错误并通过我了解的所有功能buffer.rewind()

Buffer java.nio.Buffer.rewind() 
Rewinds this buffer. The position is set to zero and the mark is discarded.

所以在从磁盘读取之后buffer.rewind(),我能够看到写入磁盘的值。

于 2020-08-15T12:26:45.283 回答