> On 15 Apr 2025, at 07:52, Cay Horstmann <cay.horstm...@gmail.com> wrote: > > > > Il 14/04/25 23:46, Ron Pressler ha scritto: >>> On 14 Apr 2025, at 21:48, Remi Forax <fo...@univ-mlv.fr> wrote: >>> >>> >>> Hi Ron, >>> i think you need to close the inputReader >>> >>> public static String output(String... args) { >>> ProcessBuilder processBuilder = new ProcessBuilder(args); >>> try { >>> Process process = processBuilder.start(); >>> try (BufferedReader reader = process.inputReader()) { >>> return reader.lines().collect(Collectors.joining("\n")); >>> } >>> } catch (IOException e) { >>> throw new IOError(e); >>> } >>> } >> When the process terminates, the InputStream underlying the pipe is closed >> (after being drained and the unread bytes served by a ByteArrayInputStream), >> which *I think* should be sufficient, but I could be wrong. >> — Ron > > Reading the process output into a string or string stream raises a number of > worries. > > * Do I need to wait for the process to complete?
I don’t know all the error conditions, but since you’re reading the stream until its end, and this pipe ends when the process closes, then I don’t think you need to also wait for the process complete, but you may want to call waitFor to get the exit status. > * Do I need to close anything? It seems to me that all the pipes are closed when the process ends, so no, but I’m not an expert in this area. > * How exactly do I use getInputStream()/inputReader() with *extreme care*, as > the API doc warns me? I think that note cautions that if you want to use that pair of methods *together*, then be careful because they’re both reading from the same underlying stream. > > If it is safe to call > > builder.start().inputReader().lines() > > or > > builder.start().getInputStream().readAllBytes() > > without waiting or closing, then the API doc could say so. I think so, and so I guess the doc should say that, but there could be error conditions that complicate matters (e.g. what happens if your thread is interrupted?) > If not, then maybe a safe method to get the entire output would be > appropriate for Process? > In what form, though? A Stream<String> of lines seems the most flexible and convenient — calling .toList() on it seems especially convenient. But perhaps that hypothetical Process.inputLines() method could also have the returned Stream<String> throw an exception if the process terminates with a non-zero code, making things even more convenient, like so: var p = new ProcessBuilder("ls", "-al").start(); try { var lines = p.inputLines().toList(); ... } catch (ProcessFailedException ex) { var errorLines = p.errorLines().toList(); ... } — Ron