【问题标题】:Why the command line utility hangs when invoked through java program?为什么命令行实用程序在通过 java 程序调用时会挂起?
【发布时间】:2012-05-09 11:29:34
【问题描述】:

在接下来的任务中,我需要您的建议和指导。 我正在使用带有命令行实用程序的 libdmtx,它读取 ECC200 数据矩阵条形码的图像文件,读取它们的内容,并将解码的消息写入标准输出。 我想在 linux 平台上的 java 程序中使用这个命令行实用程序。我正在使用 ubuntu linux。我已经在我的 linux 机器上安装了 libdmtx。当我调用命令时

dmtxread -n /home/admin/ab.tif

在linux终端上,它立即给出图像中条形码的解码值。

当我要使用我的 java 程序调用此命令时,代码会在执行命令时出现问题,并且 dotn 会给出输出。 看起来程序正在处理或挂起。

以下是我调用以下命令的 java 代码

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;


public class Classtest {

    public static void getCodes(){

        try 
        { 
            Process p; 
            String command[]=new String[3];
            command[0]="dmtxread";
            command[1]="-n";
            command[2]="/home/admin/ab.tif";

            System.out.println("Command : "+command[0]+command[1]+command[2]);
            p=Runtime.getRuntime().exec(command);  //I think hangs over here.

            BufferedReader reader=new BufferedReader(new InputStreamReader(p.getErrorStream()));
            String line=reader.readLine();
            if(line==null){
                reader=new BufferedReader(new InputStreamReader(p.getInputStream()));
                line=reader.readLine();
                System.out.print("Decoded      :- "+line);
            }else{
                System.out.print("Error      :- "+line);
            }
            System.out.println(p.waitFor());

        }catch(IOException e1) {
            e1.getMessage();
            e1.printStackTrace();
        }catch(InterruptedException e2) {
            e2.getMessage();
            e2.printStackTrace();
        } 


    }
    public static void main(String args[]){
        getCodes();
    }

}

请朋友们告诉我我的代码哪里出错了。

我参考了以下文章,但没有得到任何帮助

http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=1

朋友们请多多指教! 谢谢!

这是我使用 ProcessBuilder 类的新代码,此代码也提供与上述代码相同的输出,即它挂在行 进程进程 = pb.start();

public class Test {

public static void main(final String[] args) throws IOException, InterruptedException {
    //Build command 
    List<String> commands = new ArrayList<String>();
    commands.add("dmtxread");
    commands.add("-n");
    commands.add("/home/admin/ab.tif");
    System.out.println(commands);

    //Run macro on target
    ProcessBuilder pb = new ProcessBuilder(commands);
    pb.redirectErrorStream(true);
    Process process = pb.start();

    //Read output
    StringBuilder out = new StringBuilder();
    BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
    String line = null, previous = null;
    while ((line = br.readLine()) != null){
        System.out.println(line);
    }

    //Check result
    if (process.waitFor() == 0)
        System.out.println("Success!");
    System.exit(0);

    //Abnormal termination: Log command parameters and output and throw        ExecutionException
    System.err.println(commands);
    System.err.println(out.toString());
    System.exit(1);
}

}

请指导我解决这个问题。 谢谢你!

【问题讨论】:

    标签: java linux barcode-scanner runtime.exec processbuilder


    【解决方案1】:

    readLine 会阻塞,直到它从错误流中接收到新行。因此,如果没有输出,您的程序将无法通过第一个 readLine。

    为简单起见,我建议您使用ProcessBuilder 而不是Runtime.exec(),这样您就可以合并两个 InputStream,如下所示:

    ProcessBuilder builder = new ProcessBuilder(cmd,arg0,arg1);
    builder.redirectErrorStream(true);
    Process process = builder.start();
    

    所以,现在你可以从一个中读取。

    或者,您可以使用单独的线程来使用两个 InputStream。

    希望有帮助

    【讨论】:

    • 感谢您的回复,我将按照您在我的代码中的建议进行更改,并让您知道结果。
    • 请检查我在上面的问题中添加的代码,它已经实现了你给出的解决方案,但仍然没有结果。
    • 嗯,现在看起来不错。有几件事可以尝试:1) 使用你的程序来运行类似ls 的命令。有输出吗? 2) 注释掉整个while 块,看看它是否到达了waitFor。 3) 使用调试器单步执行,看看它走了多远(或者如果你不知道怎么做,就在每行之间打印一些东西)
    • 当我在我的问题中执行第二个代码时,它的行为与第一个相同,但经过很长时间它给了我想要的输出,但现在问题是代码花费的时间用于扫描一张图像上的条形码
    【解决方案2】:

    您的流消费代码非常混乱。您尝试从 stderr 读取单行,然后放弃该读取器,然后尝试从 stdout 读取单行。

    1. 如果程序没有向 stderr 打印任何内容,您将在第 2 行挂起。
    2. 如果程序向 stderr 发送 太多 内容以填满其缓冲区,则程序本身将阻塞,而您的 Java 将阻塞在 waitFor。
    3. 这些都适用于标准输出。

    您链接的那篇文章详细介绍了使用流程输出流的正确方法。接受这个建议,没有人能比这更好的建议。

    【讨论】:

    • 谢谢先生的回复!正如你所建议的那样,我已经根据参考链接对我的代码进行了更改,我添加了作者在文章第四页添加的 streamgobbler 类,并尝试运行该程序,但它没有打印任何 System.out.println (“命令 : ”);行
    • 从您发布的代码来看,您如何得出代码块在哪一行并不明显。请给出一些令人信服的论据,证明您的代码确实在该特定行阻塞。
    • 当我在我的问题中执行第二个代码时,它的行为与第一个相同,但经过很长时间它给了我想要的输出,但现在问题是代码花费的时间用于扫描一张图像上的条形码。
    【解决方案3】:

    我不确定您的程序到底发生了什么以及它挂在哪里(您可以使用调试器或跟踪输出来检查),但可能的情况是:

    假设程序要输出 2 行文本。或者只有一行但进入标准错误。您的代码从标准输出读取仅 1 行,然后等待进程退出。这意味着子程序可能会等待读者阅读下一行,因此它会在write 中等待,直到有人解除管道阻塞——永远。

    当你从命令行运行dmtxread时,输出管道没有阻塞,所以程序运行得很好。

    【讨论】:

    • 谢谢先生的回复!正如你所建议的,我检查了代码,但它既没有给出任何错误,也没有给出输出。
    • @Param-Ganak:那么也许reader.readLine() 永远挂起,等待程序输出一些东西?
    • 我真的不知道程序哪里出错了我把问题中的参考链接看了三遍,但没有用。我敢肯定,当命令在我的第一个代码中执行时,程序会一直等待应用程序的回复。
    猜你喜欢
    • 1970-01-01
    • 2013-06-05
    • 1970-01-01
    • 2014-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多