我正在编写一个 Java 程序来创建一个 cURL 命令并执行它。我没有遇到任何问题,除了一个命令不允许我将标准输出流式传输到我的程序中。 stdout 包含执行 future cURL 命令所需的信息。
我一直在使用 -o 命令将标准输出输出到 .txt 文件,但这不起作用,除非我在执行 cURL 命令后立即停止 Java 程序。 我还尝试了几种不同的流媒体技术,但似乎都没有用。
不幸的是,与我通信的 API 需要帐户信息才能执行许多命令,但我将共享不显示我的用户名和密码的代码。
这是执行并返回我 future 命令所需的值的命令:
curl -o C:\Users\friza\eclipse-workspace\CanaryCoalMine\birdseed.txt -k -J -X POST -v --include -H "X-gts-token:xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx" https://api.gts.geant.net/taas/api/v2/projects/CanaryCoalMine/types/OneHost/reservations
这是 birdseed.txt 文件的输出。最后的五位数是我需要的:
HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)
Date: Thu, 20 Jun 2019 16:25:07 GMT
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.google.com/recaptcha http://www.springframework.org http://java.sun.com/jsp https://www.google.com/jsapi https://www.google.com https://www.gstatic.com code.jquery.com ajax.googleapis.com https://*.bootstrapcdn.com https://*.cloudflare.com; img-src 'self' http://195.113.161.164:* https://www.gstatic.com/recaptcha code.jquery.com; style-src 'self' 'unsafe-inline' https://*.bootstrapcdn.com https://*.cloudflare.com https://fonts.googleapis.com code.jquery.com; font-src 'self' https://themes.googleusercontent.com https://*.bootstrapcdn.com https://*.cloudflare.com; frame-src 'self' 'unsafe-inline' https://www.google.com; object-src 'none'
Expect-CT: enforce; max-age=3600
Strict-Transport-Security: max-age=31622400; includeSubDomains; preload
Referrer-Policy: no-referrer
Feature-Policy: geolocation 'none';midi 'none';notifications 'none';push 'none';sync-xhr 'none';microphone 'none';camera 'none';magnetometer 'none';gyroscope 'none';speaker 'self';vibrate 'none';fullscreen 'self';payment 'none';
10940
这是我用来执行上述代码的 Java 方法:
public static void createType(String tokenHeader, String dslEncoded) {
String curlCommand = "curl -o C:\\Users\\friza\\eclipse-workspace\\CanaryCoalMine\\birdseed.txt -k -J -X POST -v --include -H "+tokenHeader
+" -H \"Content-Type: application/x-www-form-urlencoded\" -d \"script="
+dslEncoded+
"\" https://api.gts.geant.net/taas/api/v2/projects/CanaryCoalMine/types";
try {
//execute Curl Command to create new type
Process process = Runtime.getRuntime().exec(curlCommand);
System.out.println("Creating Type...");
System.out.println("Sent: " + curlCommand);
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("IO EXCEPTION :( ");
e.printStackTrace();
}
}
长话短说 预期:执行 cURL 命令后,我希望在不停止执行该命令的 Java 程序的情况下查看文件中的给定输出。
实际结果:在 Java 程序上单击“停止”之前,无法在 .txt 文件中看到上述输出。在我能够从文件中提取最后五位数字之前,无法继续执行该程序。由于未知原因无法直接流式传输。
最佳答案
添加到 user207421 所说的......
这很可能是缓冲区读取问题。
处理外部进程非常困难,如果外部程序的缓冲区已满,它将停止响应/工作,直到该缓冲区被清除。
因此,当从外部进程读取缓冲区时,这些读取进程必须在它们自己的线程中进行。
这是我的团队不久前为处理外部流程所做的一些工作中的一个简单示例。
主要方法...
package processbuilder;
import processbuilder.streamreader.PrintStreamStreamReader;
public class CurlProcessBuilder {
public static void main(String... args) throws Exception {
ProcessBuilder processBuilder = new ProcessBuilder("curl", "-v", "-s", "-k", "https://localhost:8443");
Process process = processBuilder.start();
PrintStreamStreamReader outReader = new PrintStreamStreamReader(System.out, process.getInputStream());
Thread outThread = new Thread(outReader);
outThread.start();
PrintStreamStreamReader errReader = new PrintStreamStreamReader(System.err, process.getErrorStream());
Thread errThread = new Thread(errReader);
errThread.start();
int exitValue = process.waitFor();
System.out.println("Exit value: " + exitValue);
}
}
用于从进程缓冲区读取的线程...
package processbuilder.streamreader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
public class PrintStreamStreamReader implements Runnable {
private PrintStream printStream;
private InputStream inputStream;
public PrintStreamStreamReader(PrintStream printStream, InputStream inputStream) {
this.printStream = printStream;
this.inputStream = inputStream;
}
@Override
public void run() {
try {
int c;
byte[] data = new byte[1024];
while ((c = inputStream.read(data, 0, data.length)) != -1) {
printStream.write(data, 0, c);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
处理长时间运行的外部进程是一件痛苦的事情。这里有一些其他资源来解释这些问题。我不得不自己多次阅读所有这些链接,以弄清楚实际所说的内容以及为什么让所有内容都“恰到好处”如此困难。
关于java - 在我停止执行 cURL 命令的 java 程序之前,cURL -o 命令不会输出到文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56690392/