为什么通过java程序调用命令行实用程序时挂起?

为什么通过java程序调用命令行实用程序时挂起?,java,linux,barcode-scanner,runtime.exec,processbuilder,Java,Linux,Barcode Scanner,Runtime.exec,Processbuilder,在接下来的任务中,我需要你们的建议和指导。 我正在使用libdmtx,它附带一个命令行实用程序,用于读取ECC200数据矩阵条形码的图像文件,读取其内容,并将解码后的消息写入标准输出。 我想在linux平台上的java程序中使用这个命令行实用程序。我使用ubuntu linux。我已经在我的linux机器上安装了libdmtx。当我调用命令时 dmtxread-n/home/admin/ab.tif 在linux终端上,它立即给出图像中条形码的解码值 当我要使用java程序调用这个命令时,代码会

在接下来的任务中,我需要你们的建议和指导。 我正在使用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();
    }

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

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

请引导我的朋友们! 谢谢大家!

这是我使用ProcessBuilder类的新代码,该代码还提供了与上面代码相同的输出,即挂起在第行 Process进程=pb.start()

公共类测试{
公共静态void main(最终字符串[]args)引发IOException、InterruptedException{
//生成命令
List命令=new ArrayList();
命令。添加(“dmtxread”);
命令。添加(“-n”);
commands.add(“/home/admin/ab.tif”);
System.out.println(命令);
//在目标上运行宏
ProcessBuilder pb=新的ProcessBuilder(命令);
pb.重定向错误流(真);
Process进程=pb.start();
//读取输出
StringBuilder out=新的StringBuilder();
BufferedReader br=新的BufferedReader(新的InputStreamReader(process.getInputStream());
String line=null,previous=null;
而((line=br.readLine())!=null){
系统输出打印项次(行);
}
//检查结果
if(process.waitFor()==0)
System.out.println(“成功!”);
系统出口(0);
//异常终止:记录命令参数、输出和抛出ExecutionException
System.err.println(命令);
System.err.println(out.toString());
系统出口(1);
}
}

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

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

假设程序想要输出两行文本。或者只有一行,但进入标准。代码只从标准输出读取1行,然后等待进程退出。这意味着子程序可能会等待读卡器读取下一行,因此它会在
write
中等待,直到有人解锁管道——永远


当您从命令行运行
dmtxread
时,输出管道上没有阻塞,因此程序运行良好。

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

  • 如果程序没有将任何内容打印到stderr,您将挂在第2行
  • 如果程序向stderr发送了太多的内容,使其填满了缓冲区,那么程序本身将被阻塞,Java将在
    waitFor
    处被阻塞
  • 这两者都适用于标准输出

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

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

    为简单起见,我建议您使用
    ProcessBuilder
    而不是
    Runtime.exec()
    ,它允许您按如下方式合并两个输入流:

    ProcessBuilder builder = new ProcessBuilder(cmd,arg0,arg1);
    builder.redirectErrorStream(true);
    Process process = builder.start();
    
    所以,现在你可以从其中一个读出来

    或者,您可以使用单独的线程来使用这两个输入流


    希望对您有所帮助

    谢谢您的回复,先生。我将按照您在我的代码中的建议进行更改,并让您知道结果。请检查我在上面问题底部添加的代码,该代码实现了您给出的解决方案,但仍然没有结果。嗯,现在看起来不错。有两件事需要尝试:1)使用您的程序运行类似于
    ls
    的命令。有输出吗?2) 注释掉整个
    while
    块,看看它是否到达waitFor。3) 使用调试器一步一步地进行调试,看看它能走多远(或者如果您不知道如何做到这一点,只需在每行之间打印一些内容)当我执行问题中的第二个代码时,其行为与第一个代码相同,但经过很长时间后,它给了我一个我想要的输出,但现在的问题是扫描一张图像上的条形码所用的时间。谢谢先生的回复!正如您所建议的,我已经根据参考链接对代码进行了更改,我添加了streamgobbler类,作者在文章的第四页中添加了该类,并尝试运行该程序,但它没有在System.out.println(“命令:”)中打印任何内容;从您发布的代码中可以看出,您是如何得出代码阻塞在哪一行的结论的。请给出一些令人信服的证据,证明你的代码确实在那一行阻塞。当我执行我问题中的第二个代码时,它的行为与第一个代码相同,但经过很长时间后,它给了我一个我想要的输出,但现在的问题是代码扫描一幅图像上的条形码所花费的时间。谢谢你,先生回复正如您所建议的,我签入代码,但它既没有给出任何错误,也没有给出任何输出。@Param Ganak:那么可能
    reader.readLine()
    永远挂起,等待程序输出一些东西?我真的不知道程序哪里出了问题,我在
    ProcessBuilder builder = new ProcessBuilder(cmd,arg0,arg1);
    builder.redirectErrorStream(true);
    Process process = builder.start();