Używam środowiska wykonawczego do uruchamiania poleceń wiersza polecenia z mojego programu Java. Jednak nie jestem świadomy tego, w jaki sposób mogę uzyskać dane wyjściowe zwracane przez polecenie.
Oto mój kod:
Runtime rt = Runtime.getRuntime();
String[] commands = {"system.exe", "-send" , argument};
Process proc = rt.exec(commands);
Próbowałem, System.out.println(proc);
ale to nic nie zwróciło. Wykonanie tego polecenia powinno zwrócić dwie liczby oddzielone średnikiem. Jak mogę uzyskać to w zmiennej do wydrukowania?
Oto kod, którego teraz używam:
String[] commands = {"system.exe", "-get t"};
Process proc = rt.exec(commands);
InputStream stdIn = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(stdIn);
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("<OUTPUT>");
while ((line = br.readLine()) != null)
System.out.println(line);
System.out.println("</OUTPUT>");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
Ale nie otrzymuję nic jako moje wyjście, ale kiedy uruchamiam to polecenie samodzielnie, działa dobrze.
pwd && ls
nie tylko wykonuje pojedynczy plik, kiedy robisz to w powłoce, wykonuje zarówno pliki wykonywalne, jak/bin/pwd
i/bin/ls
. Jeśli chcesz robić takie rzeczy w Javie, musisz zrobić coś takiego{"/bin/bash","-c", "pwd && ls"}
. Prawdopodobnie nie masz już tego pytania, ale inni ludzie mogą, więc pomyślałem, że mogę na nie odpowiedzieć.stdout
istderr
wyjścia. Jeśli nie będziesz ich słuchać jednocześnie, jeden z nich zapełni się podczas czytania drugiego. Program, którego słuchasz, będzie wtedy blokował próby zapisu do wypełnionego bufora, podczas gdy na drugim końcu twój program będzie blokował próby odczytu z bufora, który nigdy nie wróciEOF
. Państwo musi czytać z obu strumieni jednocześnie.Szybszy sposób jest następujący:
Co jest w zasadzie skondensowaną wersją tego:
Wiem, że to pytanie jest stare, ale publikuję tę odpowiedź, ponieważ myślę, że może to być szybsze.
źródło
\A
w wyrażeniu regularnym oznacza początek ciągu i musiałem uciec przed ukośnikiem.Oprócz używania
ProcessBuilder
zgodnie z sugestią Senthil, pamiętaj, aby przeczytać i zaimplementować wszystkie zalecenia When Runtime.exec () nie .źródło
ProcessBuilder
ponieważ teraz zaleca się dwukrotnie. Używając aProcessBuilder
, można połączyć strumienie wyjściowe i strumienie błędów, aby ułatwić jednoczesne wykorzystanie obu.Jeśli użytkownik ma już Apache commons-io dostępny w ścieżce klas, można użyć:
źródło
Możemy również użyć strumieni do uzyskania wyniku polecenia:
źródło
Wspomniane odpowiedzi @Senthil i @Arend ( https://stackoverflow.com/a/5711150/2268559 )
ProcessBuilder
. Oto przykład użyciaProcessBuilder
z określeniem zmiennych środowiskowych i folderu roboczego dla polecenia:źródło
W chwili pisania tego tekstu wszystkie inne odpowiedzi zawierające kod mogą spowodować zakleszczenie.
Procesy mają ograniczony bufor dla
stdout
istderr
wyjścia. Jeśli nie będziesz ich słuchać jednocześnie, jeden z nich zapełni się, gdy będziesz próbował czytać drugi. Na przykład możesz czekać na odczyt,stdout
podczas gdy proces czeka na zapisstderr
. Nie można czytać zstdout
bufora, ponieważ jest on pusty, a proces nie może zapisywać wstderr
buforze, ponieważ jest pełny. Czekacie na siebie wiecznie.Oto możliwy sposób odczytu danych wyjściowych procesu bez ryzyka zakleszczenia:
Kluczem jest użycie,
ProcessBuilder.redirectErrorStream(true)
które przekierujestderr
dostdout
strumienia. Pozwala to na odczytanie pojedynczego strumienia bez konieczności przełączania się międzystdout
istderr
. Jeśli chcesz zaimplementować to ręcznie, będziesz musiał zużywać strumienie w dwóch różnych wątkach, aby upewnić się, że nigdy nie będziesz blokować.źródło
Jeśli piszesz na Kotlinie, możesz użyć:
źródło
Na podstawie poprzedniej odpowiedzi:
źródło
Prawie to samo, co inne fragmenty na tej stronie, ale po prostu organizując rzeczy według funkcji , zaczynamy ...
Funkcja Class:
źródło
Spróbuj przeczytać
InputStream
część środowiska wykonawczego:Może być również konieczne odczytanie strumienia błędów (
proc.getErrorStream()
), jeśli proces drukuje wyjście błędu. Jeśli używasz, możesz przekierować strumień błędów do strumienia wejściowegoProcessBuilder
.źródło