如何从 Java 读取命令行输出(通过 Runtime.getRuntime().exec(...))

发布于 2024-09-24 03:50:52 字数 2221 浏览 0 评论 0原文

我试图在 Swing 应用程序中提供一些有关符号链接存在的信息。 GUI 有一个 JTextArea resultTextArea 和一个 JTextField statusField。这是 Dialog 类中的代码:

public void checkForSymLinks(File... dirs) {
    for (File dir : dirs) {
        try {
            Process p = Runtime.getRuntime().exec("find -type l", null, dir);
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(p.getInputStream()));
            String line = null;
            while ((line = in.readLine()) != null) {
                resultTextArea.append(line);
            }
        } catch (IOException ex) {
            Logger.getLogger(SymbolicLinkSearchResultDialog.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    statusField.setText("SymLinks found! // FIXME");
}

我尝试将 Process p = Runtime.getRuntime().exec("find -type l", null, dir); 替换为:

ProcessBuilder pb = new ProcessBuilder("find -type l");
pb.directory(dir).redirectErrorStream(true);
Process p = pb.start(); 

但这没有帮助。

问题在于,它既不向 resultTextArea 写入任何内容,也不到达最后一行设置 statusField 的代码。尽管 GUI 保持响应,但它似乎挂在某个地方。

我在关闭对话框时得到以下堆栈跟踪:

java.io.IOException: Cannot run program "find -type l" (in directory "/home/johndoe/Desktop/test"): error=2, No such file or directory
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:1024)

我已经尝试了/usr/bin/find type -l和许多其他事情...... 有什么想法我做错了吗?

PS:操作系统为Linux。

奇怪的是:

def symLinkCheck(dirs: Array[File]) = {                              
  dirs.foreach{ dir =>                                                        
    val p = Runtime.getRuntime().exec("find -type l", null, dir)                    
    val in = new BufferedReader(new InputStreamReader(p.getInputStream)) 
    var line: String = null
    while({line = in.readLine; line} != null){
      println(line)
    }
  }
}

我在 Scala 中尝试了这段代码,它运行没有问题。我不确定我的问题是否与 Swing 有关?

编辑:问题肯定与 Swing 有关。

如果我在 theGUI.setVisible(true) 之前调用该方法,它可以工作,但之后它没有。

我已经尝试过 SingUtilities.invokeLater 但这没有帮助。

I'm trying to present some information in a Swing application about the existance of symlinks.
The GUI has a JTextArea resultTextArea and a JTextField statusField. This is the code inside the Dialog class:

public void checkForSymLinks(File... dirs) {
    for (File dir : dirs) {
        try {
            Process p = Runtime.getRuntime().exec("find -type l", null, dir);
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(p.getInputStream()));
            String line = null;
            while ((line = in.readLine()) != null) {
                resultTextArea.append(line);
            }
        } catch (IOException ex) {
            Logger.getLogger(SymbolicLinkSearchResultDialog.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    statusField.setText("SymLinks found! // FIXME");
}

I tried and replaced Process p = Runtime.getRuntime().exec("find -type l", null, dir); by:

ProcessBuilder pb = new ProcessBuilder("find -type l");
pb.directory(dir).redirectErrorStream(true);
Process p = pb.start(); 

But that did not help.

The problem is that it somehow neither writes anything to the resultTextArea nor reaches the code to set the statusField in the last line. It seems to hang somewhere, alhough the GUI stays responsive.

I get the following stacktrace upon closing the dialog:

java.io.IOException: Cannot run program "find -type l" (in directory "/home/johndoe/Desktop/test"): error=2, No such file or directory
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:1024)

I already tried /usr/bin/find type -l and many other things...
Any ideas what I'm done wrong?

PS: Operationg system is Linux.

Weird thing:

def symLinkCheck(dirs: Array[File]) = {                              
  dirs.foreach{ dir =>                                                        
    val p = Runtime.getRuntime().exec("find -type l", null, dir)                    
    val in = new BufferedReader(new InputStreamReader(p.getInputStream)) 
    var line: String = null
    while({line = in.readLine; line} != null){
      println(line)
    }
  }
}

I tried this code in Scala and it worked without a problem. I'm not really sure anymore if my problem is maybe related to Swing?

EDIT: The problem is definitely related to Swing.

If I call the method before theGUI.setVisible(true) it works, but after that it doesn't.

I already tried SingUtilities.invokeLater but that didn't help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

给我一枪 2024-10-01 03:50:52

你没有说你正在使用哪个操作系统。假设您的 find 命令语法是正确的(在 Mac OSX 上不正确),我认为您应该:

  1. 同时使用 stdout 和 stderr。您需要同时执行此操作以避免阻塞行为。请参阅此答案,了解
  2. 从以下位置收集退出代码的 更多详细信息通过 Process.waitFor() 生成的进程

You don't say which OS you're using. Assuming your find command syntax is correct (it's not correct on Mac OSX), I think you should be:

  1. consuming both stdout and stderr. You need to do this concurrently to avoid blocking behaviour. See this SO answer for more details
  2. collecting the exit code from the spawned process via Process.waitFor()
悲欢浪云 2024-10-01 03:50:52

您可以通过比较 File.getCanonicalPath()File.getAbsolutePath() 的结果,在 Java 中执行此操作,而不是运行 Unix 命令来查找符号链接。

更多详细信息请参阅问题。

Instead of running a Unix command to find symlinks, you could do it in Java, by comparing the results of File.getCanonicalPath() and File.getAbsolutePath().

More details in this question.

江挽川 2024-10-01 03:50:52

我发现问题:在构建 GUI 后,未从事件分派线程调用​​该方法。

I found the Problem: The method was not called from the event dispatch thread, after the GUI was constrcuted.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文