1

linux版本:MINT 14 netbeans 7.2

我最近才开始编程,我面临着这个困难。我有一个带有 2 个 jtextarea 的 GUI,一个是我们键入命令的地方,一个是命令输出的地方(第三个将针对错误(linux,而不是 java)实现,这可以正常工作,目前对于我的原型,到目前为止:

命令的输出进入文本区域,但缺少提示,我尝试了很多东西,但无法解决它,我也浏览了很多常见问题解答,但提示用于多种方式,但不是在 shell迅速的。欢迎帮助。

我已经插入了流程构建器类的代码(请暂时忽略大写字母等最佳实践,它只是一个原型,如果原型有效,我将有编码员跟进)

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.Reader;
    import java.io.StringWriter;
    import java.io.Writer;

    /**
     *
     * @author bane
     */
    public class myprocessBuilderRunCommand {
        public static String myprocessBuilderRunCommand(String command, boolean waitForResponse) {

    String response = "";

    ProcessBuilder pb = new ProcessBuilder("bash", "-c", command);
    pb.redirectErrorStream(true);

    System.out.println("Linux command: " + command);

    try {
    Process shell = pb.start();

    if (waitForResponse) {

    // To capture output from the shell
    InputStream shellIn;
            shellIn = shell.getInputStream();

    // Wait for the shell to finish and get the return code
    int shellExitStatus = shell.waitFor();
    System.out.println("Exit status" + shellExitStatus);

    response = convertStreamToStr(shellIn);

    shellIn.close();
    }

    }

    catch ( IOException | InterruptedException e) {
    System.out.println("Error occured while executing Linux command. Error Description: "
    + e.getMessage());
    }

    return response;
    }

    /*
    * To convert the InputStream to String we use the Reader.read(char[]
    * buffer) method. We iterate until the Reader return -1 which means
    * there's no more data to read. We use the StringWriter class to
    * produce the string.
    */

    public static String convertStreamToStr(InputStream is) throws IOException {

    if (is != null) {
    Writer writer = new StringWriter();

    char[] buffer = new char[1024];
    try {
    Reader reader;
            reader = new BufferedReader(new InputStreamReader(is,
     "UTF-8"));
    int n;
    while ((n = reader.read(buffer)) != -1) {
    writer.write(buffer, 0, n);
    }
    } finally {
    is.close();
    }
    return writer.toString();
    }
    else {
    return "";
    }
    }
    }
4

1 回答 1

0

据我了解,您正在寻找一种从 java 代码执行命令并在不同窗口中显示输出的方法。这是一个工作示例,它执行命令echo 1然后返回true输出1false输出0,(在所有其他情况下抛出异常)。这样您就可以将输出重定向到您想要的任何位置。

我还添加了设置工作路径和环境变量,这对于您的特定示例不是必需的,因此您可以将其删除。

  1. 您可以将此代码复制粘贴为一个类,将其编译为 jar 并运行它。
  2. 它在 WSL Ubuntu 16.04 中得到验证。
  3. 通过设置binaryCommand[0]="touch";binaryCommand[1]="1";,重新编译和运行.jar文件来验证设置工作目录。

    import java.io.BufferedReader;
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    import java.util.Arrays;
    import java.util.Map;
    import java.util.StringJoiner;
    
    public class GenerateOutput {
    
        /**
         * This code can execute a command and return the binary value of it's output if it 
         * is actually binary.
         * 
         * compile this project into a .jar and run it with for example:
         * java -jar readOutputOfCommand.jar
         * 
         * @param args
         * @throws Exception 
         */
        public static void main(String[] args) throws Exception {
            boolean answerYes = false; // no yes answer to any command prompts is needed.
    
            // to execute a command with spaces in it in terminal, put them in an array of Strings.
            String[] binaryCommand = new String[2];
    
            // write a command that gives a binary output:
            binaryCommand[0] = "echo";
            binaryCommand[1] = "1";
    
            // pass the commands to a method that executes them
            System.out.println("The output of the echo command = "+executeCommands(binaryCommand,answerYes));
        }
    
        /**
         * This executes the commands in terminal. 
         * Additionally it sets an environment variable (not necessary for your particular solution)
         * Additionally it sets a working path (not necessary for your particular solution)
         * @param commandData
         * @param ansYes
         * @throws Exception 
         */
        public static boolean executeCommands(String[] commands,Boolean ansYes) throws Exception {
            String capturedCommandOutput = null;
            System.out.println("Incoming commandData = "+Arrays.deepToString(commands));
            File workingDirectory = new File("/mnt/c/testfolder b/");
    
            // create a ProcessBuilder to execute the commands in
            ProcessBuilder processBuilder = new ProcessBuilder(commands);
    
            // this is not necessary but can be used to set an environment variable for the command
            processBuilder = setEnvironmentVariable(processBuilder); 
    
            // this is not necessary but can be used to set the working directory for the command
            processBuilder.directory(workingDirectory);
    
            // execute the actual commands
            try {
    
                    Process shell = processBuilder.start();
    
                 // capture the output stream of the command
                 BufferedReader reader = new BufferedReader(new InputStreamReader(shell.getInputStream()));
                StringJoiner sj = new StringJoiner(System.getProperty("line.separator"));
                reader.lines().iterator().forEachRemaining(sj::add);
                capturedCommandOutput = sj.toString();
                System.out.println("The output of this command ="+ capturedCommandOutput);
    
                 // here you connect the output of your command to any new input, e.g. if you get prompted for `yes`
                 new Thread(new SyncPipe(shell.getErrorStream(), System.err)).start();
                 new Thread(new SyncPipe(shell.getInputStream(), System.out)).start();
                PrintWriter stdin = new PrintWriter(shell.getOutputStream());
    
                //This is not necessary but can be used to answer yes to being prompted
                if (ansYes) {
                    System.out.println("WITH YES!");
                stdin.println("yes");
                }
    
                // write any other commands you want here
    
                stdin.close();
    
                // this lets you know whether the command execution led to an error(!=0), or not (=0).
                int returnCode = shell.waitFor();
                System.out.println("Return code = " + returnCode);
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            return retrieveBooleanOutput(capturedCommandOutput);
        }
    
        private static boolean retrieveBooleanOutput(String commandOutput) throws Exception {
            if (commandOutput != null && commandOutput.length() == 1) { 
                if (commandOutput.contains("0")) {
                    return false;
                } else if (commandOutput.contains("1")) {
                    return true;
                }
            }
            throw new Exception("The output is not binary.");
        }
    
        /**
         * source: https://stackoverflow.com/questions/7369664/using-export-in-java
         * @param processBuilder
         * @param varName
         * @param varContent
         * @return
         */
        private static ProcessBuilder setEnvironmentVariable(ProcessBuilder processBuilder){
            String varName = "variableName";
            String varContent = "/mnt/c/testfolder a/";
    
            Map<String, String> env = processBuilder.environment();
             System.out.println("Setting environment variable "+varName+"="+varContent);
             env.put(varName, varContent);
    
             processBuilder.environment().put(varName, varContent);
    
             return processBuilder;
        }
    }
    
    
    class SyncPipe implements Runnable
    {   
        /**
         * This class pipes the output of your command to any new input you generated
         * with stdin. For example, suppose you run cp /mnt/c/a.txt /mnt/b/
         * but for some reason you are prompted: "do you really want to copy there yes/no?
         * then you can answer yes since your input is piped to the output of your
         * original command. (At least that is my practical interpretation might be wrong.)
         * @param istrm
         * @param ostrm
         */
        public SyncPipe(InputStream istrm, OutputStream ostrm) {
            istrm_ = istrm;
            ostrm_ = ostrm;
        }
        public void run() {
    
          try
          {
              final byte[] buffer = new byte[1024];
              for (int length = 0; (length = istrm_.read(buffer)) != -1; )
              {
                  ostrm_.write(buffer, 0, length);                
                  }
              }
              catch (Exception e)
              {
                  e.printStackTrace();
              }
          }
          private final OutputStream ostrm_;
          private final InputStream istrm_;
    }
    
于 2019-04-17T17:00:59.933 回答