Java 是否有更好的方法读取流程';输入流,然后使用指定的方法进行处理?

Java 是否有更好的方法读取流程';输入流,然后使用指定的方法进行处理?,java,io,bufferedreader,processbuilder,Java,Io,Bufferedreader,Processbuilder,我正在编写一个程序,完成以下工作: 使用ProcessBuilder运行命令(如“svn info”或“svn diff”) 从进程的getInputStream()读取命令的输出 对于命令的输出,我希望: 解析输出并获取所需内容,稍后使用,或者: 将输出直接写入指定的文件 现在,我要做的是使用BufferedReader逐行读取命令输出的内容,并将它们保存到ArrayList,然后决定是否只扫描这些行以查找某些内容或将这些行写入文件 显然,这是一个丑陋的实现,因为如果我想将命令的输出保存到

我正在编写一个程序,完成以下工作:

  • 使用ProcessBuilder运行命令(如“svn info”或“svn diff”)
  • 从进程的
    getInputStream()
    读取命令的输出
  • 对于命令的输出,我希望:
    • 解析输出并获取所需内容,稍后使用,或者:
    • 将输出直接写入指定的文件
  • 现在,我要做的是使用
    BufferedReader
    逐行读取命令输出的内容,并将它们保存到
    ArrayList
    ,然后决定是否只扫描这些行以查找某些内容或将这些行写入文件

    显然,这是一个丑陋的实现,因为如果我想将命令的输出保存到文件中,就不需要ArrayList。那么,您有什么建议,以更好的方式进行吗?

    以下是我的一些代码:

    使用此命令运行命令并读取进程的输出

    private ArrayList<String> runCommand(String[] command) throws IOException {
        ArrayList<String> result = new ArrayList<>();
        _processBuilder.command(command);
    
        Process process = null;
        try {
            process = _processBuilder.start();
            try (InputStream inputStream = process.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
                String line;
                while ((line = bufferedReader.readLine()) != null) {
                    result.add(line);
                }
            }
        }
        catch (IOException ex) {
            _logger.log(Level.SEVERE, "Error!", ex);
        }
        finally {
            if (process != null) {
                try {
                    process.waitFor();
        }
                catch (InterruptedException ex) {
                    _logger.log(Level.SEVERE, null, ex);
                }
            }
        }
    
    return result;
    }
    
    private ArrayList runCommand(字符串[]命令)引发IOException{
    ArrayList结果=新建ArrayList();
    _processBuilder.command(command);
    Process=null;
    试一试{
    进程=_processBuilder.start();
    try(InputStream-InputStream=process.getInputStream();
    InputStreamReader InputStreamReader=新的InputStreamReader(inputStream);
    BufferedReader BufferedReader=新的BufferedReader(inputStreamReader)){
    弦线;
    而((line=bufferedReader.readLine())!=null){
    结果。添加(行);
    }
    }
    }
    捕获(IOEX异常){
    _logger.log(Level.severy,“Error!”,ex);
    }
    最后{
    if(进程!=null){
    试一试{
    process.waitFor();
    }
    捕获(中断异常例外){
    _logger.log(Level.SEVERE,null,ex);
    }
    }
    }
    返回结果;
    }
    
    在一种方法中,我可以这样做:

    ArrayList<String> reuslt = runCommand(command1);
    
    for (String line: result) {
        // ...parse the line here...
    }
    
    ArrayList<String> result = runCommand(command2);
    File file = new File(...filename, etc...);
    
    try (PrintWriter printWriter = new PrintWriter(new FileWriter(file, false))) {
        for (String line: result) {
            printWriter.println(line);
        }
    }
    
    ArrayList reuselt=runCommand(command1);
    for(字符串行:结果){
    //…在这里分析行。。。
    }
    
    另一方面,我可以这样做:

    ArrayList<String> reuslt = runCommand(command1);
    
    for (String line: result) {
        // ...parse the line here...
    }
    
    ArrayList<String> result = runCommand(command2);
    File file = new File(...filename, etc...);
    
    try (PrintWriter printWriter = new PrintWriter(new FileWriter(file, false))) {
        for (String line: result) {
            printWriter.println(line);
        }
    }
    
    arraylistresult=runCommand(command2);
    文件=新文件(…文件名等);
    try(PrintWriter PrintWriter=new PrintWriter(new FileWriter(file,false))){
    for(字符串行:结果){
    printWriter.println(行);
    }
    }
    
    在ArrayList中返回流程输出对我来说似乎是一个很好的抽象。那么
    runCommand()
    的调用者就不必担心命令是如何运行的或输出是如何读取的。额外列表使用的内存可能并不重要,除非您的命令非常冗长

    我唯一能看到这是一个问题的时候是调用方希望在命令仍在运行时开始处理输出,这里的情况似乎不是这样


    对于您不想首先复制到内存中的非常大的输出,一个选项是让
    runCommand()
    接受一个回调,如Guava的
    LineProcessor
    ,它将为输出的每一行调用该回调。然后
    runCommand()
    仍然可以抽象出整个流程的运行、读取输出以及随后关闭所有内容,但是数据可以在回调运行时传递给回调,而不是等待方法在一个数组中返回整个响应。

    我不认为在某些情况下无用地存储文本是性能问题。尽管如此,为了保持清洁,最好编写两种方法:

    private ArrayList<String> runCommand(String[] command)
    
    private void runCommandAndDumpToFile(String[] command, File file)
    
    private ArrayList runCommand(字符串[]命令)
    私有void runcommanddumptofile(字符串[]命令,文件)
    

    (您的问题不太清楚,但我假设您在运行进程之前知道是将输出写入文件还是处理它。)

    我忘记添加的是,类似svn diff的命令在某些情况下可能会生成大于10MB的输出。啊,你的意思是我可以编写一些实现相同接口的处理器,并将其中一个作为参数传递给runCommand方法吗?是的,可以有一个处理器将每一行复制到一个文件中,另一个处理器解析这些行并对其进行处理。然后,当您调用
    runCommand()
    时,您可以将其传递给其中一个处理器,以决定对输出应用哪种处理。我尝试了这一点并成功了,代码看起来好多了。我将投票并接受这个答案。