我正在编写一个创建cURL命令并执行它的Java程序。除了一个命令不允许我将标准输出流式传输到我的程序外,我没有任何问题。标准输出具有执行将来的cURL命令所需的信息。
我一直在使用-o命令将标准输出输出到.txt文件,但是除非我在执行cURL命令后立即停止Java程序,否则这将无法工作。 我也尝试了几种不同的流技术,但似乎没有一种起作用。
不幸的是,我正在与之通信的API需要帐户信息才能执行许多命令,但是我将共享不显示用户名和密码的代码。
这是执行并返回将来命令所需的值的命令:
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
这是birdeed.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();
}
}
TL; DR 预期:cURL命令执行后,我希望在文件中看到给定的输出,而不会停止执行该命令的Java程序。
实际结果:在我按Java程序上的STOP键之前,无法在.txt文件中看到以上输出。在我能够从文件中提取最后五位数字之前,无法继续执行该程序。由于某些未知原因而无法直接流式播放。
答案 0 :(得分:0)
要添加到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();
}
}
}
处理长时间运行的外部过程很痛苦。这里是解释问题的其他一些资源。我必须自己多次阅读所有这些链接,以弄清楚实际上在说什么,以及为什么很难使所有内容“正确”。