Я хочу использовать внешний инструмент при извлечении некоторых данных (цикл через строки). Для этого я сначала использовал Runtime.getRuntime().exec() для его выполнения. Но потом моя добыча стала очень медленной. Поэтому я ищу возможность запускать внешний инструмент в каждом экземпляре цикла, используя один и тот же экземпляр оболочки.
Я узнал, что я должен использовать ProcessBuilder. Но это еще не работает.
Вот мой код для проверки выполнения (с учетом ответов здесь, на форуме уже):
public class ExecuteShell {
ProcessBuilder builder;
Process process = null;
BufferedWriter process_stdin;
BufferedReader reader, errReader;
public ExecuteShell() {
String command;
command = getShellCommandForOperatingSystem();
if(command.equals("")) {
return; //Fehler! No error handling yet
}
//init shell
builder = new ProcessBuilder( command);
builder.redirectErrorStream(true);
try {
process = builder.start();
} catch (IOException e) {
System.out.println(e);
}
//get stdout of shell
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
errReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
//get stdin of shell
process_stdin = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
System.out.println("ExecuteShell: Constructor successfully finished");
}
public String executeCommand(String commands) {
StringBuffer output;
String line;
try {
//single execution
process_stdin.write(commands);
process_stdin.newLine();
process_stdin.flush();
} catch (IOException e) {
System.out.println(e);
}
output = new StringBuffer();
line = "";
try {
if (!reader.ready()) {
output.append("Reader empty \n");
return output.toString();
}
while ((line = reader.readLine())!= null) {
output.append(line + "\n");
return output.toString();
}
if (!reader.ready()) {
output.append("errReader empty \n");
return output.toString();
}
while ((line = errReader.readLine())!= null) {
output.append(line + "\n");
}
} catch (Exception e) {
System.out.println("ExecuteShell: error in executeShell2File");
e.printStackTrace();
return "";
}
return output.toString();
}
public int close() {
// finally close the shell by execution exit command
try {
process_stdin.write("exit");
process_stdin.newLine();
process_stdin.flush();
}
catch (IOException e) {
System.out.println(e);
return 1;
}
return 0;
}
private static String getShellCommandForOperatingSystem() {
Properties prop = System.getProperties( );
String os = prop.getProperty( "os.name" );
if ( os.startsWith("Windows") ) {
//System.out.println("WINDOWS!");
return "C:/cygwin64/bin/bash";
} else if (os.startsWith("Linux") ) {
//System.out.println("Linux!");
return"/bin/sh";
}
return "";
}
}
Я хочу назвать это в другом классе, таком как этот Testclass:
public class TestExec{
public static void main(String[] args) {
String result = "";
ExecuteShell es = new ExecuteShell();
for (int i=0; i<5; i++) {
// do something
result = es.executeCommand("date"); //execute some command
System.out.println("result:\n" + result); //do something with result
// do something
}
es.close();
}
}
Моя проблема в том, что выходной поток всегда пуст:
ExecuteShell: Constructor successfully finished
result:
Reader empty
result:
Reader empty
result:
Reader empty
result:
Reader empty
result:
Reader empty
Я прочитал ветку здесь: Java Process with Input/Output Stream
Но фрагментов кода было недостаточно, чтобы заставить меня двигаться, я что-то упускаю. Я действительно не очень много работал с разными потоками. И я не уверен, поможет ли мне сканер. Я был бы очень признателен за помощь.
В конечном счете, моя цель состоит в том, чтобы многократно вызывать внешнюю команду и делать это быстро.
РЕДАКТИРОВАТЬ: я изменил цикл, так что es.close() находится снаружи. И я хотел добавить, что я не хочу только этого внутри цикла.
РЕДАКТИРОВАТЬ: Проблема со временем заключалась в том, что команда, которую я вызвал, вызвала ошибку. Когда команда не вызывает ошибки, время приемлемо.
Спасибо за ответ