0

I have an application that runs through the windows command line, and I want to be able to copy all of the data that has been sent to the console and append it to a file for debugging purposes. Whenever an exception happens, a report is saved to the file system that includes the exception stack trace and the full console.

I cannot redirect the entire console to my file because I need to be able to obtain console input from the user.

System.out.toString() doesn't return the console, but a string representation of the object itself.

Ptolemy2002
  • 169
  • 2
  • 15
  • 3
    I don't think that's generally possible. You'll probably need to write you're own `println` function that calls some logging function, and calls `System.out.println`. – Carcigenicate Apr 17 '19 at 12:39
  • 3
    You should use appropriate logging tools like log4j that allows you to use multiple appenders. – ernest_k Apr 17 '19 at 12:39
  • use ``System.setOut`` with a custom stream of your own, that keeps track of anything received. But this is not a good pattern I think – spi Apr 17 '19 at 12:51

2 Answers2

1

Even if not the best idea, one solution could be:

public static void main(String[] xxx) {
    System.setOut(new DoublePrintStream(System.out, "/myfile.txt"));
    System.setErr(new DoublePrintStream(System.err, "/errors.txt"));

    System.out.println("this works");
    try { throw new RuntimeException("oulala");} catch(Exception e) { e.printStackTrace(); }

    //System.out.close(); // maybe required at the end of execution
}

class DoublePrintStream extends PrintStream {
        private final OutputStream fos;

        DoublePrintStream(OutputStream out, String filename){
            super(out);

            try {
                fos = new FileOutputStream(new File(filename));
            } catch (FileNotFoundException e) {
                throw new AssertionError("cant create file", e);
            }
        }

        @Override
        public void write(byte[] buf, int off, int len) {
            super.write(buf, off, len);

            try {
                fos.write(buf, off, len);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        public void close() {
            try {
                fos.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            } finally {
                super.close();
            }
        }
    }

so you have output in the console + in a file, and all errors in a separate file.

Even if logging frameworks are way better, this solution has the advantage to require no code change at all.

PS: in a multithreaded context, you should also synchronize the methods of DoublePrintStream

spi
  • 1,673
  • 13
  • 19
  • Is there any way that I could configure this to also show the input that the user inserted into the console? Currently, the input is omitted. – Ptolemy2002 Apr 18 '19 at 20:02
  • I know that I can use the Scanner class to obtain input from the command line, but this doesn't seem to be included in the output file. – Ptolemy2002 Apr 18 '19 at 20:03
0

You can use this format to get console output to a text file if you are using CMD

javac {Programe_name}.java & java {Programe_name} > {Output_file_name>}

for example, if java programme is World.java

javac World.java & java World > out.txt

  • _"I cannot redirect the entire console to my file because I need to be able to obtain console input from the user."_ I interpret this as a requirement to have display to the console, too. – spi Apr 17 '19 at 13:37
  • If you use some specific char when getting user input try this code javac {Programe_name}.java & java {Programe_name} > {Output_file_name>} & findstr {patter} {Output_file_name} > Output_file2.txt – Wishwa Gayan Apr 17 '19 at 14:47