У меня есть скрипт Matlab, который выполняет множество системных вызовов через функцию system()
. Однако я заметил, что функция очень медленная (имеет много накладных расходов). Например, вызов
tic;system('echo');toc;
занимает в среднем 0,08 секунды. С большим количеством системных вызовов накладные расходы становятся неприемлемыми.
Я попытался заменить вызовы на Java (что я не знаю, я просто копирую и вставляя откуда-то еще), следующим образом
runtime=java.lang.Runtime.getRuntime();
process=runtime.exec('commandStringThatNeedsToBeExecuted');
status=process.waitFor();
Когда он работает, он работает хорошо, и накладные расходы значительно сокращаются. Однако у меня две проблемы.
Первая проблема: для выполнения некоторых команд происходит сбой (но это не прерывается при вызове system()
), в зависимости от программы, которую я вызываю. В частности (но это, вероятно, не имеет значения), когда я делаю вызовы pdflatex
, все работает нормально, а когда я pdflatex
в ImageMagick convert
, выполнение не выполняется. Итак, чтобы понять эти различия в поведении, мой первый вопрос: каковы основные отличия между вызовом system()
Matlab system()
и системным вызовом через Java?
Вторая проблема: как получить результат команды (я имею в виду, что будет отображаться на экране, если, например, команда была выполнена в командном окне DOS), которую я могу получить из второго выходного аргумента system()
функционировать?
Чтобы получить результат, попробуйте следующее:
p = java.lang.ProcessBuilder({'cmd', 'arg1', 'arg2'}).start();
reader = java.io.BufferedReader(java.io.InputStreamReader(p.getInputStream()));
str = char(java.util.Scanner(reader).useDelimiter('\A').next());
Вы можете заменить последнюю строку следующим:
...
sb = java.lang.StringBuilder();
while true;
line = reader.readLine();
if isnumeric(line); % Test for NULL
break;
else
sb.append(sprintf('%s\n',char(line)));
end;
end
str = char(sb.toString());
Первый быстрее, если в этом случае много выходных system()
в этом случае system()
matlab system()
очень медленная), а вторая - более четкая и гибкая.
Что касается того, почему это иногда терпит неудачу, я не уверен. Вы так же строите командную строку? Иногда идентичные командные строки работают, а иногда и не работают? Вы возитесь с окружающей средой?
Различия в том, насколько я знаю, система может активно выполнять команды cmd (Windows), тогда как для команд runtime.exec() вам нужно заранее вставить cmd/c.
Чтобы прочитать результат процесса, выполните следующие действия:
p.waitFor();
try (BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
final StringBuilder string = new StringBuilder();
String line;
try {
while (input.ready() && (line = input.readLine()) != null) {
string.append(line + "\n");
}
} catch (IOException e) {}
return string.toString();
} catch (Exception ex) {
ex.printStackTrace();
}
Это будет подключаться к выходному процессу процесса и читать его по строкам в строковом устройстве.
Я работаю над проектом, где мне нужно запустить множество команд оболочки и вызвать внешние инструменты из Matlab. Эта медлительность вызвала у меня много боли.
Я нашел вышеописанный ProcessBuilder
-based очень полезным (спасибо!), Но все же нужно было настроить различные вещи. Здесь моя реализация, надеюсь, что это полезно для будущих посетителей, приезжающих сюда...