Trying to use Apache Common exec with bytebuffer to push output from one command to another command in java

huangapple go评论65阅读模式
英文:

Trying to use Apache Common exec with bytebuffer to push output from one command to another command in java

问题

以下是您提供的代码的翻译部分:

我的计划是使用 `ByteBuffer`**Apache Common Exec** 来将一个命令的输出作为另一个命令的输入发送

我可以使用 `PipedOutputStream``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`,然后将其作为下一个命令的输入提供

以下是我尝试的代码但它不像预期的那样工作我可以看到缓冲区被填充但它没有写入磁盘在上面的代码中当我使用 `PipedOutputStream``PipedInputStream` 时会写入磁盘)。

在这种情况下我使用了 `ByteBufferBackedOutputStream``ByteBufferBackedInputStream`,这些都是自定义类我从另一个帖子中获取了实现

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);
    }

}

如果您需要进一步的帮助或有其他问题,请随时提问。

英文:

My plan is to use ByteBuffer with Apache Common Exec to send output from one command as an input to another command.

I am able to do this using PipedOutputStream and PipedInputStream and below is the code which works fine.

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());
}

The above code works fine but I want to get the output from the first command, and put it to ByteBuffer and provide it as the input to the next command.

Below is the code which I am trying to do but it is not working as expected (I am able to see the buffer getting populated but it is not writing to the disk, which was happening in the above code when I used PipedOutputStream and PipedInputStream).

In this case I am using ByteBufferBackedOutputStream and ByteBufferBackedInputStream which are custom classes and I got the implementation from another post here at 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);
}
}

答案1

得分: 0

问题出在 bytebufferposition 位于最后一个位置,所以当写入时,它找不到缓冲区内保存的元素。通过试验和查看所有函数,我了解到了 buffer.rewind()

> Buffer java.nio.Buffer.rewind()
> 重绕此缓冲区。位置被设置为零,标记被丢弃。

所以在从磁盘读取后,只需运行 buffer.rewind(),就可以看到写入磁盘的值。

英文:

Okay so the issue was that the position for the bytebuffer was at the last location so when the write happened it didn't find the elements saved within the buffer.
By trail and error and going through all the functions I came to know about buffer.rewind()

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

so after the read from the disk just ran buffer.rewind() and I was able to see the values written to disk.

huangapple
  • 本文由 发表于 2020年8月11日 19:01:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/63356827.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定