{"id":4792,"date":"2014-03-30T15:22:23","date_gmt":"2014-03-30T15:22:23","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2014\/03\/30\/run-a-sub-process-provide-input-and-output-to-it-correctly-in-java-collection-of-common-programming-errors\/"},"modified":"2014-03-30T15:22:23","modified_gmt":"2014-03-30T15:22:23","slug":"run-a-sub-process-provide-input-and-output-to-it-correctly-in-java-collection-of-common-programming-errors","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2014\/03\/30\/run-a-sub-process-provide-input-and-output-to-it-correctly-in-java-collection-of-common-programming-errors\/","title":{"rendered":"Run a sub process, provide input and output to it correctly in Java-Collection of common programming errors"},"content":{"rendered":"<p>You need to copy the input and output between the subprocess&#8217; streams and <code>System<\/code> streams (<code>System.in<\/code>, <code>System.out<\/code> and <code>System.err<\/code>). This is related to my recent quesion. The best solution I have found so far is:<\/p>\n<pre><code>import java.io.FileInputStream;\nimport java.io.FilterInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.lang.reflect.Field;\nimport java.nio.ByteBuffer;\nimport java.nio.channels.AsynchronousCloseException;\nimport java.nio.channels.FileChannel;\n\nclass StreamCopier implements Runnable {\n    private InputStream in;\n    private OutputStream out;\n\n    public StreamCopier(InputStream in, OutputStream out) {\n        this.in = in;\n        this.out = out;\n    }\n\n    public void run() {\n        try {\n            int n;\n            byte[] buffer = new byte[4096];\n            while ((n = in.read(buffer)) != -1) {\n                out.write(buffer, 0, n);\n                out.flush();\n            }\n        }\n        catch (IOException e) {\n            System.out.println(e);\n        }\n    }\n}\n\nclass InputCopier implements Runnable {\n    private FileChannel in;\n    private OutputStream out;\n\n    public InputCopier(FileChannel in, OutputStream out) {\n        this.in = in;\n        this.out = out;\n    }\n\n    public void run() {\n        try {\n            int n;\n            ByteBuffer buffer = ByteBuffer.allocate(4096);\n            while ((n = in.read(buffer)) != -1) {\n                out.write(buffer.array(), 0, n);\n                out.flush();\n            }\n            out.close();\n        }\n        catch (AsynchronousCloseException e) {}\n        catch (IOException e) {\n            System.out.println(e);\n        }\n    }\n}\n\npublic class Test {\n    private static FileChannel getChannel(InputStream in)\n            throws NoSuchFieldException, IllegalAccessException {\n        Field f = FilterInputStream.class.getDeclaredField(\"in\");\n        f.setAccessible(true);\n        while (in instanceof FilterInputStream)\n            in = (InputStream)f.get((FilterInputStream)in);\n        return ((FileInputStream)in).getChannel();\n    }\n\n    public static void main(String[] args)\n            throws IOException, InterruptedException,\n                   NoSuchFieldException, IllegalAccessException {\n        Process process = Runtime.getRuntime().exec(\"sh -i +m\");\n        Thread outThread = new Thread(new StreamCopier(\n                process.getInputStream(), System.out));\n        outThread.start();\n        Thread errThread = new Thread(new StreamCopier(\n                process.getErrorStream(), System.err));\n        errThread.start();\n        Thread inThread = new Thread(new InputCopier(\n                getChannel(System.in), process.getOutputStream()));\n        inThread.start();\n        process.waitFor();\n        System.in.close();\n        outThread.join();\n        errThread.join();\n        inThread.join();\n    }\n}\n<\/code><\/pre>\n<p>The tricky part here is to extract a channel from <code>System.in<\/code>. Without this you will not be able to interrupt the thread that reads input when the subprocess terminates.<\/p>\n<p>This approach has a serious drawback: after closing <code>System.in<\/code> you can no longer read from it. The workaround that I&#8217;m currently using is to have a single input redirecting thread used for all subprocesses.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>You need to copy the input and output between the subprocess&#8217; streams and System streams (System.in, System.out and System.err). This is related to my recent quesion. The best solution I have found so far is: import java.io.FileInputStream; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Field; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousCloseException; import java.nio.channels.FileChannel; class StreamCopier [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-4792","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/4792","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=4792"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/4792\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=4792"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=4792"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=4792"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}