java - 我只是用java编写了一个wrapcommand,但有时它不打印命令输出。为什么

标签 java shell process runtime.exec

我只是用java写了一个简单的命令包装器,这是构造函数:

Process process;
Thread in;
Thread out; 

public CommandWrapper(Process process) {
    this.process = process;
    final InputStream inputStream = process.getInputStream();
    // final BufferedReader
    //final BufferedReader r = new BufferedReader(new InputStreamReader(inputStream));
    final byte[] buffer = new byte[1024];
    out = new Thread() {
        // String line;
        int lineNumber = 0;

        public void run() {
            try {
                while (true) {
                    int count = inputStream.read(buffer);
                    System.out.println(lineNumber + ":"
                            + new String(buffer, 0, count - 1));
                    // line=r.readLine();
                    // System.out.println(lineNumber+":"+line);
                    lineNumber++;
                }
            } catch (Exception e) {

            }
        }
    };
    final BufferedReader reader = new BufferedReader(new InputStreamReader(
            System.in));
    final OutputStream outputStream = process.getOutputStream();
    in = new Thread() {
        String line;

        public void run() {
            try {
                //while (true) {
                    outputStream.write((reader.readLine() + "/n")
                            .getBytes());
                    outputStream.flush();
                //}
            } catch (Exception e) {

            }
        }
    };
}

public void startIn() {
    in.start();
}

这是它调用的时候:

public static void main(String[] args) {
    try {
        CommandWrapper command = new CommandWrapper(Runtime.getRuntime()
                .exec("wget www.google.com"));
        //command.startIn();
        command.startOut();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

当我运行 ls -l 或其他本地命令等简单命令时,它工作正常,但是当我想运行 wget 命令时,它不会打印任何内容作为输出。我知道为什么。

最佳答案

根据您所显示的代码以及对如何使用它的描述,最好的猜测是发生了异常,而您默默地接受了它。每当你有一个空的 catch block 时就会发生这种情况,如下所示:

catch (Exception e) {
}

您的 out 线程的 run() 方法中恰好有一个。

默默地接受异常是极其糟糕的做法。

你应该永远不要这样做!根据您的应用程序,适当的解决方案会有所不同,但由于您正在编写控制台应用程序,您可能希望打印异常的堆栈跟踪。在 Java 中,这是通过 e.printStackTrace() 完成的:

catch (Exception e) {
    e.printStackTrace();
}

另一种选择(在这种特定情况下可能不合适)是重新抛出异常,可能是在将其包装在另一个异常中(例如您已经处理过的异常)之后专为您的应用程序编写):

catch (Exception e) {
    throw e;
}
// or
catch (Exception e) {
    throw new MyOwnException(e);
}

执行这两项操作(打印堆栈跟踪或重新抛出)将确保没有异常被忽视。

但是,没有规则无异常(exception);)

在某些情况下,适合使用空的 catch 子句。如果您知道某些操作可能会引发异常,而您只想在异常发生时继续执行,那么空的 catch 子句是一个好方法。但是,适用的情况仅限于(至少)以下条件:

  1. 您必须知道异常的具体类型。永远不想捕获一般异常(即 catch (Exception e) 因为这可能会因您无法预测的任何原因而抛出。如果您使用空的 catch 子句,始终捕获特定的异常类型(例如 IOException)

  2. 您必须知道抛出异常的原因。您应该只吞下您知道其来源的异常。如果您吞下任何其他异常,您最终会像这种情况一样,您的代码不会执行您期望的操作,并且您无法理解为什么。被吞没的异常非常难以调试,因为它们被吞没了,从而被隐藏了。

  3. 你必须知道你不关心异常。使用空catch子句的原因主要是(阅读:)来处理您正在使用的代码将某些内容视为异常的情况,而您却没有。在这种情况下,“异常(exception)”的意思是“实际上不应该发生的事情,如果发生了,那就是严重错误。”

何时适用空 catch 子句的示例:
假设您正在使用其他人的代码打开一个文件进行读取,给定文件的绝对路径。如果文件不存在,大多数此类例程都会引发异常 - 客户端代码(即调用“打开文件例程”的代码)的工作是在尝试打开文件之前确保文件存在。例如,如果运行程序的用户没有读取文件的权限,也会引发异常。

现在,您可能并不真正关心为什么文件无法打开,但如果不能打开,您只想继续 - 在这种情况下,您会吞下所有与读取相关的异常文件(在 Java 中,可能是某种IOException)。 请注意,您吞下所有异常 - 仅吞下与打开文件相关的异常!

关于java - 我只是用java编写了一个wrapcommand,但有时它不打印命令输出。为什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14035551/

相关文章:

java - 在 https 连接 header 中设置用户代理属性

java - Struts 2修改JSON变量名

shell - 使用 .load 的 meteor shell

ios - apple在调解中心审核你的消息需要多长时间

java - 如何用数组引用这里

java - 为什么我的数组没有填充对象/显示?

android - 为什么使用 Android ADB shell 的 SQLite 3 命令返回 "permission denied"?

python - 运行得到错误认为python的命令

Unix后台进程异常停止

创建线程后调用execv