2

I'm new to Java, so apologies if any of this is unclear - I want to print out what is on the console to a text file also - however I only want it to print to the file at the end - so basically it will run through all the programs (which is a guessing game), and then once complete it will ask the user to enter a file name and then print what is on the console to that file. I'm somewhat familiar with PrintWriter and BufferedWriter etc but I'm not sure what to do when I want to print out results that exist on the console such as below (where the questions are system.out.print and the digits 3, 18, 19 are user input). Any help would be much appreciated!

Please guess a number between 1 and 20: 3

Too low, try again. Please guess a number between 1 and 20: 18

Too low, try again. Please guess a number between 1 and 20: 19

Perfect!

    System.out.println("Enter a file name: ");
    String fileName = Keyboard.readInput();

    File myFile = new File(fileName);

    try (PrintWriter pw = new PrintWriter(new FileWriter(fileName))) {
        pw.write(??????);
    } catch (IOException e) {
        System.out.println(e.getMessage());
    }
Community
  • 1
  • 1
Logan
  • 45
  • 1
  • 7
  • Possible duplicate of [How to write console output to a txt file](https://stackoverflow.com/questions/1994255/how-to-write-console-output-to-a-txt-file). Please get in the habit of searching using both Stack Overflow and your favorite search engine before posting questions. – MarsAtomic Sep 05 '18 at 23:09
  • 2
    @Logan If all you wanted to do was save the results of the console when the user wants to at the end then you could just call some utility method instead of println() that takes a String as a parameter and both writes to System.out and appends that String + "\n" to a StringBuilder object and write that StringBuilder to a FileOutputStream. Just let me know if you would like me to expand with an actual answer! – GurpusMaximus Sep 05 '18 at 23:40
  • @GurpusMaximus Yeah I think that's basically what I want to do - I've seen a few examples/suggestions elsewhere that do a similar thing but I'm just not too sure how it would work in practice - so each time where I am currently using system.out I would use a new method that would both write to system.out and also add that string to StringBuilder? – Logan Sep 05 '18 at 23:53

3 Answers3

2

If you wished to make a system to allow you to use System.out in order to print to console while also printing to a file, you could create a wrapper for the PrintStream in order to make it also write to a file. This can be done like this:

public void setupLogger() {
    PrintStream stream=System.out;
    try {
        File file=new File(System.getProperty("user.dir")+"/log.txt");
        file.delete();
        file.createNewFile();
        System.setOut(new WrapperPrintStream(stream,file));
    } catch (IOException e) {
        e.printStackTrace();
    }

    for (int i = 0; i <100 ; i++) {
        System.out.println("Log test "+i);
    }


}
class WrapperPrintStream extends PrintStream{

    private PrintStream defaultOutput;

    public WrapperPrintStream(@NotNull PrintStream out, File file) throws FileNotFoundException {
        super(new PrintStream(new FileOutputStream(file),true), true);
        defaultOutput =out;

    }

    @Override
    public void println(String x) {
        super.println(x);
        defaultOutput.println(x);
    }

    @Override
    public void println() {
        super.println();
        defaultOutput.println();
    }
    //etc for all methods.
}

However, I recommend using an API like Log4J which does this all for you automagically.

Ryan_DS
  • 750
  • 7
  • 28
  • I like this approach because it actually overrides println() which is more natural than making a utility method as in my approach! – GurpusMaximus Sep 06 '18 at 00:20
  • I agree, the only problem is that the overriding methods can get quite large. It sucks the underlying method #write(String) is private. Otherwise, we could cover almost every method in the printstream class with only 2-3 overrides. – Ryan_DS Sep 06 '18 at 01:54
1

Comments have been added for clarification on functionality

package com.so.test;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;

public class Main {

    //Declare StringBuilder as global.
    private static StringBuilder systemOut = new StringBuilder();

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        //Instead of writing only to System.out only also write to a StringBuilder
        writeLnToStreams("Hello!");
        //Attempt to write to File
        try {
            FileOutputStream outputStream = new FileOutputStream(scanner.nextLine());
            outputStream.write(systemOut.toString().getBytes());
        } catch (IOException e) {
            //Will write only to System.err
            e.printStackTrace();
        }
    }

    /**
     *
     * @param output the output to write to System.out and the global StringBuilder
     */
    private static void writeToStreams(String output) {
        System.out.println(output);
        systemOut.append(output);
    }

    /**
     *
     * @param output the output to write to System.out and the global StringBuilder
     */
    private static void writeLnToStreams(String output) {
        System.out.println(output);
        systemOut.append(output).append("\n");
    }
}
GurpusMaximus
  • 441
  • 5
  • 14
0

At first I didn't understand the question too well but I think I understand it now. My demo uses methods for input and output, similar to what GurpusMaximus showed in his answer (+1 to him), but I use different methods for getting input and writing output.

Here is an example demo:

BufferedReader inputStream = null;
PrintWriter outputStream = null;
String writeString = "";

public void testMethod() {

    File file = new File("text.txt");

    try {
        inputStream = new BufferedReader(new InputStreamReader(System.in));
        outputStream = new PrintWriter(file);

        // Example console text
        println("Enter some text: ");
        String str = read();
        println("Entered: "+str);

        // Do this when you are done with the console and want to write to the file
        outputStream.print(writeString);
        inputStream.close();
        outputStream.close();

    } catch (IOException e) {
        e.printStackTrace();
    }
}

// Custom print method that also saves what was printed
public void println(String str) {
    System.out.println(str);
    writeString += str + System.lineSeparator(); // You can use the line separator call
                                                 // to format the text on different lines in
                                                 // the file, if you want that
}

// Custom read method that gets user input and also saves it
public String read() {
    try {
        String str = inputStream.readLine();
        writeString += str + System.lineSeparator();
        return str;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

Let me know if this is more related to what you are looking for.

0xCursor
  • 2,242
  • 4
  • 15
  • 33