Есть ли лучший способ для чтения из входного потока процесса, а затем обрабатывать с использованием указанных методов? - PullRequest
0 голосов
/ 18 января 2012

Я пишу программу, выполняющую следующие работы:

  1. Запустите команду с помощью ProcessBuilder (например, «svn info» или «svn diff»);
  2. Считайте выводкоманда из процесса getInputStream();
  3. Получив команду, я хочу либо:
    • Разобрать вывод и получить то, что я хочу, и использовать его позже, ИЛИ:
    • Записать вывод непосредственно в указанный файл.

Теперь я использую 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;
}

и в одном способе я могу сделать так:

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);
    }
}

Ответы [ 2 ]

1 голос
/ 18 января 2012

Возвращение вывода процесса в ArrayList кажется мне хорошей абстракцией.Тогда вызывающему runCommand() не нужно беспокоиться о том, как была выполнена команда или как прочитан вывод.Память, используемая дополнительным списком, вероятно, не будет существенной, если ваша команда не очень длинная.

Единственный раз, когда я мог видеть это как проблему, было бы, если бы вызывающая сторона хотела начать обработку вывода, пока команда ещевыполняется, что здесь не так.

Для очень больших выходных данных, которые вы не хотите сначала копировать в память, одним из вариантов будет runCommand() принять обратный вызов, как в Guava LineProcessor, что он будет вызывать для каждой строки вывода.Тогда runCommand() все еще может абстрагировать всю работу по запуску процесса, чтению выходных данных и последующему закрытию всего, но данные могут быть переданы обратному вызову, когда он выполняется, вместо того, чтобы ждать, пока метод вернет весь ответ в одноммассив.

0 голосов
/ 18 января 2012

Я не думаю, что это проблема производительности, в которой вы в некоторых случаях бесполезно сохраняете текст.Тем не менее, для чистоты, возможно, было бы лучше написать два метода:

private ArrayList<String> runCommand(String[] command)

private void runCommandAndDumpToFile(String[] command, File file)

(из вашего вопроса было не совсем понятно, но я предполагаю, что вы знаете, прежде чем запускать свой процесс, будете ли вы просто писатьвывод в файл или обработать его.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...