在我停止执行cURL命令的Java程序之前,cURL -o命令不会输出到文件

时间:2019-06-20 16:32:49

标签: java curl

我正在编写一个创建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文件中看到以上输出。在我能够从文件中提取最后五位数字之前,无法继续执行该程序。由于某些未知原因而无法直接流式播放。

1 个答案:

答案 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();
        }
    }
}

处理长时间运行的外部过程很痛苦。这里是解释问题的其他一些资源。我必须自己多次阅读所有这些链接,以弄清楚实际上在说什么,以及为什么很难使所有内容“正确”。