java通过命令获取批处理文件的输出

时间:2019-08-08 18:47:07

标签: java batch-file runtime

我需要在Java应用程序中执行.bat文件。假设我有一个文本文件,其中包含以下示例内容:

{
    "id": 12,
    "name": "test"
}

在我的.bat文件中,我有一个用于输出文本文件内容的命令。这就是我的.bat文件内容:

#some other commands
more path\to\file.txt

最后,这是我执行以下.bat文件的Java代码:

Process process = Runtime.getRuntime().exec("path\to\file.bat");
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
List<String> outputs = new ArrayList<>();
while ((line = reader.readLine()) != null) {
    outputs.add(line);
}

执行此代码后,outputs列表中的数据如下:

[...,
"{", 
"    "id": 12",",
"   "name": "test",",
"}"
]

我的意思是,这将逐行返回输出 。但是我希望将整个命令输出作为列表的一个索引。换句话说,我希望按命令而不是逐行输出命令(每条命令只有一个输出)。

有可能这样做吗?

编辑:我也尝试使用ProcessBuilder,但结果相同。

3 个答案:

答案 0 :(得分:4)

您声明

  

在我的.bat文件中,我有一个用于输出文本文件内容的命令。

  

我想逐个命令而不是逐行输出(每个命令只有一个输出)。

如果我正确地理解了这一点,则意味着每次要输出文件时,您只运行一次代码(一个“命令”)。也就是说,您只需要将描述的输出连接到一行中即可,此时您可以将这些行放在列表中。可以这样实现:

Process process = Runtime.getRuntime().exec("path\to\file.bat");
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder builder = new StringBuilder();
List<String> outputs = new ArrayList<>();
//if desired, append prefix
//builder.append("File: {");
while ((line = reader.readLine()) != null) {
    builder.append(line);
    //if desired, append delimiter
    //builder.append("\n");
}
//if desired, append suffix
//builder.append("}");
String concatenatedString = builder.toString();

或者,在Java 8+中,您可以执行以下操作(甚至specify details行连接在一起的方式):

Process process = Runtime.getRuntime().exec("path\to\file.bat");
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String concatenatedString = reader.lines().collect(Collectors.joining(" "));

自然,我假设您只是在使用读取文件的示例作为另一个必须实际读取进程输出的代理。如果您只需要读取文件,则不需要过程即可实现。相反,您可以这样获取文件内容:

String concatenatedString = "";
try (Stream<String> stream = Files.lines(Paths.get("path\to\text\file.txt"))) {
    concatenatedString = stream.collect(Collectors.joining(" "));
}
//catch...

现在,如果您实际上想将来自多个流程的所有文本输出连接在一起,但仅将其作为一个聚合(即,您不能一个一地连接流程输出,然后再存储它们),那么您将结束不得不执行以下操作:

  • 加入所有字符串:
    • 使用StringBuffer append或收集器join可以轻松实现此目的,如上所示。
  • 在正确的位置将它们分开:

答案 1 :(得分:0)

正如@Mofi@kriegaex所述,您应该解释批处理文件的用法。我想您已经拥有了它们(批处理文件或一些其他可执行文件),并且您不能摆脱它们,而是想执行它们并将每次执行的stdout捕获到单个List或{{ 1}}项。

您当前的实现将每行追加到Map中:

  
List

一种解决方案是使用while ((line = reader.readLine()) != null) { outputs.add(line); } 连接每个可执行文件的StringBuilder行。之后,每个串联的输出将附加到stdout中。看到此示例:

Map

之后,您可以像这样验证// Create Map for outpus. Map<String, String> outputs = new HashMap<String, String>(); // Loop through batch files. for (String bat : new String[] { "file12.bat", "file13.bat" }) { // Execute batch. Process process = Runtime.getRuntime().exec(bat); // Open Reader... BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); // ... and read contents into StringBuilder. StringBuilder contents = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { contents.append(line); contents.append("\n"); // Append newline because reader.readLine() omits it. } // Close Reader. reader.close(); // Add contents into Map. outputs.put(bat, contents.toString()); } 的内容:

Map

答案 2 :(得分:0)

您似乎不想执行System.out.println(),而是希望收集命令的所有输出并在每个命令的末尾批量打印。

然后,编写自己的CommandResultCollector类型,在其中启动StringBuffer并使用适当的换行符将字符串连接起来,作为单个命令执行的一部分,并在命令执行结束时进行转换到String并打印整个内容。

或者,您可以创建一个ArrayList并添加作为命令一部分打印的所有Strings,并在执行结束时进行迭代以在每个命令结束时将它们全部打印出来执行。

我确信,有更好的解决方案可以智能地使用Heap内存。您可以通过多种方式解决此问题,选择最简单且占用最少资源的方式。