首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java进程无法从InputStream捕获OutputStream

问Java进程无法从InputStream捕获OutputStream
EN

Stack Overflow用户
提问于 2011-11-27 09:17:27
回答 1查看 2.1K关注 0票数 3

我正在尝试使用gpg.exe --passphrase-file my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg解密(没有批处理和-是选项)。如果有人想要使用加密命令来测试gpg.exe --passphrase-file ..\BE\src\my.passphrase --symmetric --output MTR241_20111124.htm.gpg MTR241_20111124.htm,我也会提供它。

有两个案子。案例1:输出dir中不存在MTR241_20111124.htm文件。exec的命令提示符和捕获的输出流都提供相同的输出。

代码语言:javascript
复制
C:\Eclipse\workspace2\sync_inbox>gpg.exe  --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg
Reading passphrase from file descriptor 3
gpg: CAST5 encrypted data
gpg: encrypted with 1 passphrase
gpg: WARNING: message was not integrity protected

同样的消息由java和命令提示符打印。

代码语言:javascript
复制
C:\Eclipse\workspace2\sync_inbox>gpg.exe  --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg
inp>gpg.exe  --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg
gpg.exe  --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg
gpg: CAST5 encrypted data
gpg: encrypted with 1 passphrase
gpg: WARNING: message was not integrity protected

到目前为止已经足够了

Case2:当输出文件按预期的方式在命令提示符中存在时,它会询问我是否要替换。

代码语言:javascript
复制
C:\Eclipse\workspace2\sync_inbox>gpg.exe  --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg
Reading passphrase from file descriptor 3
gpg: CAST5 encrypted data
gpg: encrypted with 1 passphrase
File `MTR241_20111124.htm' exists. Overwrite? (y/N) y
gpg: WARNING: message was not integrity protected

但是这个输出来自java程序,它挂在第一行之后。它不会在控制台上打印任何行。如果我在控制台中输入'y‘,它将不接受输入和处理。它只是挂着。只有当java控制台程序接受更多的命令和进程时,我才必须手动关闭进程任务/F /IM gpg.exe。

代码语言:javascript
复制
C:\Eclipse\workspace2\sync_inbox>gpg.exe  --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg
inp>gpg.exe  --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg
gpg.exe  --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg
    --hangs here-- 

当然,正常的交互命令是有效的,比如对ex:

代码语言:javascript
复制
F:\eclipse\workspace\HTMLProcessor\BEQuery>copy hello.txt world.txt
inp>copy hello.txt world.txt
copy hello.txt world.txt
Overwrite world.txt? (Yes/No/All): y
inp>y
y
        1 file(s) copied.

下面是我的问题,为什么只有当它要求提示符是否替换现有的输出文件时,它才能捕获gpg的输出流。

我已经尝试过Runtime.exec()、ProcessBuilder、Plexus、ExpectJ、Ant在java程序中运行这个gpg.exe --它们都显示在这种特殊情况下,同样的结果无法捕获进程的输出流。我甚至尝试编写一个.bat文件来运行gpg --decrypt,但即使在这种情况下,它也无法捕获上述特殊情况下的输出流。

我认为这很重要,gpg.exe的起源。我是在便携git发行版中获得的,在bin文件夹gpg.exe是可用的。

我的问题变得非常冗长和乏味,但是对于那些喜欢指出错误java代码的人来说仍然是如此。

代码语言:javascript
复制
package com.ycs.ezlink.scheduler.cmd;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import org.apache.log4j.Logger;

public class CmdRunner {
    private static Logger logger = Logger.getLogger(CmdRunner.class);

    static class StreamGobbler extends Thread
    {
        InputStream is;
        String type;

        StreamGobbler(InputStream is, String type)
        {
            this.is = is;
            this.type = type;
        }

        public void run() {
            try {
                System.out.println("in run!");
                    System.out.println(type);
                    final byte[] buffer = new byte[1];
                    for (int length = 0; (length = is.read(buffer)) != -1;) {
                        System.out.write(buffer, 0, length);
                    }
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
        }
    }

    public static int process(String cmd){
        int exitVal = 0; 
        try {
            Runtime rt = Runtime.getRuntime();
             Process proc = rt.exec(cmd);
             // any error message?
             StreamGobbler errorGobbler = new 
                 StreamGobbler(proc.getErrorStream(), "ERROR");            

             // any output?
             StreamGobbler outputGobbler = new 
                 StreamGobbler(proc.getInputStream(), "OUTPUT");

             // kick them off
             errorGobbler.start();
             outputGobbler.start();

             // any error???
             System.out.println("Waiting for cmd process to complete " );
            exitVal = proc.waitFor();
             System.out.println("ExitValue: " + exitVal);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }    
        return exitVal;
    }

    public static void main(String[] a) throws IOException, InterruptedException, TimeoutException, ExpectJException {
        String gzipCmd = "gpg.exe  --passphrase-file C:/Eclipse/workspace2/BE/src/my.passphrase --decrypt --output C:/Eclipse/workspace2/sync_inbox/MTR241_20111124.htm C:/Eclipse/workspace2/sync_inbox/MTR241_20111124.htm.gpg";  
        //CmdRunner.process(gzipCmd); ///--fails
        //ProcessBuilder pb = new ProcessBuilder("gpg", "--passphrase-file", "C:/Eclipse/workspace2/BE/src/my.passphrase",
        "--decrypt","--output","C:/Eclipse/workspace2/sync_inbox/MTR241_20111124.htm",
        "C:/Eclipse/workspace2/sync_inbox/MTR241_20111124.htm.gpg"); ///--fails
        ProcessBuilder pb = new ProcessBuilder ("cmd");
        pb.redirectErrorStream(true);
        Process process = pb.start();
        OutputStream stdin = process.getOutputStream ();
        InputStream stderr = process.getErrorStream ();
        InputStream stdout = process.getInputStream ();
         StreamGobbler errorGobbler = new StreamGobbler(stderr, "ERROR");            
         errorGobbler.start();
         StreamGobbler stdoutGobbler = new StreamGobbler(stdout, "DEBUG");            
         stdoutGobbler.start();

         BufferedReader scan = new BufferedReader(new InputStreamReader(System.in));
         String line;
         while ((line = scan.readLine())!= null) {
                String input = line;
                System.out.println("inp>"+input);
                if (input.trim().equals("exit")) {
                    stdin.write("exit\r\n".getBytes()); 
                    stdin.flush();
                    break;
                } else {
                     stdin.write((input+"\r\n").getBytes());
                     stdin.flush();
                }
            }
         System.out.println("exited..");
        int returnCode  = process.waitFor();
        System.out.println(returnCode);
    }
}

最后一句,如果我使用gpg --batch选项,它将不再提示y/N输入,因此它会顺利运行。但我只是好奇,为什么会有这个问题。虽然我有一种感觉,gpg.exe最初是为类似Unix/Linux的平台编写的,所以可能会有一些输入输出文件重定向,但是我想知道更多的原因,以便下次我知道该查找什么。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-02-09 17:54:36

在终端中看到的输出是标准输出流、标准错误流和控制台的合并结果。您可以捕获标准输出和标准错误流。但是你不能捕获控制台。这就是为什么gpg 故意使用直接使用控制台,以防止捕获。他们为什么要这么做是有争议的。

底线:您将无法捕获直接处理控制台的程序的输入或输出流。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8284579

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档