关键词搜索

源码搜索 ×
×

使用java编写一个调用第三方可执行文件的windows命令行工具

发布2022-11-21浏览557次

详情内容

客户有一批数据需要使用一个叫wodASC.exe的程序来处理。该程序是个命令行工具,好像是用fortran写的,比较坑,后面不能带参数,只能在运行它之后,输入待处理的文件名称,选转换字段,有点繁琐,并且每次只能处理一个文件。数据文件非常多,估计好几千个,靠人工处理,几乎不可能。

一、原理

想办法写程序来处理。思路是,首先,我们写的代码,需要调用wodASC.exe;其次,调用过程中,需要与之交互。以往有写过调用外部程序的代码,但传递给外部程序的参数都是附在后面,位于同一行命令,与外部程序交互没有弄过。试了许久,好不容易弄出来了,介绍如下。

其中最为关键的地方,是通过process.getOutputStream().write()与外部程序交互,给它喂参数。

其次是命令行。我们给Process调用的命令行类似这个样子:

cmd /k c: && cd c:\\temp\\data && e:\\wodPressor\\wodASC.exe
  • 1

本命令行是一个复合命令行,里面有好几个命令,中间用 “&&” 隔开。
这个命令行意思是先到某个盘,比如c盘,然后进入指定的文件夹,调用当前程序所在位置的wodASC.exe这个程序。

二、主要代码:

private void doIt(File file, String[] option) {
    try {
        String command = getCommand(file);//装配好命令行
        Process process = Runtime.getRuntime().exec(command);

		//读取外部程序的输出
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "gbk"));
        //往外部程序输入,感觉怎么名字刚好倒过来了,getOutputStream()
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));

        String fileName = file.getName();
		
		//将文件名传给外部程序
		//“\n”是回车
        writer.write(fileName + "\n");
        //这句也很重要,推给外部程序
        writer.flush();
		
		//将选项1传给外部程序
        writer.write(option[0] + "\n");
        writer.flush();
		
		//将选项2传给外部程序
        writer.write(String.format("%s#%s", fileName, option[1]) + "\n");
        writer.flush();

		//将选项3传给外部程序
        writer.write("0\n");
        writer.flush();

		//参数喂完
        writer.close();

		//释放process
        process.destroy();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
//命令行也值得说一下
//本命令行是一个复合命令行,里面有好几个命令,中间用 "&&" 隔开。
//这个命令行意思是先到某个盘,比如c盘,然后进入指定的文件夹,调用当前程序所在位置的wodASC.exe这个程序。
private static final String CMD = "cmd /k %s: && cd %s && %s\\wodASC.exe";
private String getCommand(File f) {
    String folder = f.getParent();//待处理的文件夹
    String disk = getDisk(folder);//盘符
    return String.format(CMD, disk, folder, this._curPath);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

三、补充事项

上面给出的代码,是一次性、一口气,将多个参数喂给外部程序。但是,我在测试过程中,为方便测试,简单起见,是写了一个批处理文件来代替wodASC.exe这个外部程序。但喂参数的代码却有所不同:

1、批处理

set /p a=please input a:
echo a-%a%
set /p b=please input b:
echo b-%b%
pause>nul
  • 1
  • 2
  • 3
  • 4
  • 5

2、测试代码

public static void test() {
    ProcessBuilder builder = new ProcessBuilder("c:/temp/test.bat");
    builder.redirectErrorStream(true);
    Process process = null;
    try {
        process = builder.start();

        OutputStream stdin = process.getOutputStream();
        InputStream stdout = process.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));

        while (true) {
            String line = reader.readLine().trim();
            if (line.endsWith("input a:")) {
                writer.write("AAA\n");
                writer.flush();
            } else if (line.endsWith("input b:")) {
                writer.write("BBB\n");
                writer.flush();
            } else {
                System.out.println(line);
            }

            if (line.endsWith("pause1>nul")) {
                writer.close();
                break;
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

这里面用了while,一直在等待程序喂参数,而不是像上面那样,呼啦啦,一口气喂完。而且喂的时候,是根据程序的输出来决定喂什么参数。但这种方式,对我要真正调用的wodASC.exe却不起作用。在这个地方,着实被坑了一把。

这其中是啥原因,还不得而知。

相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载