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

时间:2012-12-26 02:59:38

标签: java shell process runtime.exec

我只是在java中编写一个简单的commandwrapper,这是构造函数:

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命令时,它不打印输出。我知道为什么。

1 个答案:

答案 0 :(得分:1)

根据您展示的代码以及您如何使用它的描述,最好的猜测是发生异常,并且您默默地吞下它。每当你有一个空catch - 块时就会发生这种情况,如下所示:

catch (Exception e) {
}

您的run()主题的out方法恰好有一个。

严重吞咽异常是非常糟糕的做法。

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

完成的
catch (Exception e) {
    e.printStackTrace();
}

另一个选项(在这种特定情况下可能不合适)是重新抛出异常,可能是在包装之后的另一个例外(例如你的一个)专门为您的申请而写的):

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

执行这两项中的任何一项(打印堆栈跟踪或重新抛出)将确保不会忽视任何异常。

但是,没有例外的规则;)

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

  1. 您必须知道异常的具体类型。从不想要捕获常规异常(即{{1因为任何你无法预测的原因可能会抛出它。如果你使用空的catch (Exception e)子句,总是捕获特定的异常类型(例如catch。< / p>

  2. 您必须知道抛出异常的原因。您应该只吞下您知道原因的异常。如果你吞下任何其他异常,你最终会像在这种情况下一样,你的代码没有达到预期的效果,你无法理解为什么。吞下的异常非常难以调试,因为它们被吞下,从而被隐藏起来。

  3. 您必须知道自己并不关心异常。使用空IOException - 子句的原因主要是(读取:仅 )处理你正在使用的代码将某些东西视为异常的情况,而不是。通过 exeptional 在这种情况下,我们的意思是“不应该发生的事情,如果真的发生了,那就是严重错误。”

  4. 适用于空catch - 条款的示例:
    假设您正在使用某些elses代码打开文件进行读取,给定文件的绝对路径。如果文件不存在,大多数此类例程会抛出异常 - 它是客户端代码(即调用“打开文件例程”的代码)的工作,以确保文件在尝试打开之前存在。例如,如果运行程序的用户没有读取文件的权限,也会抛出异常。

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