Java: Using BufferedReader and PrintWriter in Conjunction Causes Issues

how to use bufferedreader in java
how to take string input from user in java using bufferedreader
example of bufferedreader in java with inputstreamreader
how to take array input in java using bufferedreader
how to use bufferedreader in java to read integer
how to take character input in java using bufferedreader
file handling in java using bufferedreader
how to read pdf file in java using bufferedreader

I'm trying to learn about Java's io package through experimentation and from the book "Java2: the Complete Reference (5th ed.)". Below, I have tried to make a very simple program to take some input using a BufferedReader instance and deliver some simple console output with PrintWriter instances.

package io;

import java.io.*;

public class UsingPrinterWriter {
    public static void main(String argv[]) {
        PrintWriter output = new PrintWriter(System.out, true);
        Profile hypro = Profile.promptedProfile();
        output.print(hypro);
        output.close();
        return;
    }
}

class Profile {
    private String first_name;
    private String last_name;
    private int age;

    Profile() {}

    Profile(String first_name, String last_name, int age) {
        this.first_name = first_name;
        this.last_name = last_name;
        this.age = age;
    }

    void setFirstName(String fn) {
        this.first_name = fn;
        return;
    }

    void setLastName(String ln) {
        this.last_name = ln;
        return;
    }

    void setAge(int a) {
        this.age = a;
        return;
    }

    static Profile promptedProfile() {
        Profile new_profile = new Profile();

        // create the writer and reader
        PrintWriter output = new PrintWriter(System.out, true);
        BufferedReader input = new BufferedReader(new InputStreamReader(System.in));

        try {
            // prompt for first name
            output.print("Enter your first name: ");
            new_profile.setFirstName(input.readLine());

            // prompt for last name
            output.print("Enter your last name: ");
            new_profile.setLastName(input.readLine());

            // prompt for age
            output.print("Enter your age: ");
            while(true) {
                try {
                    new_profile.setAge(Integer.parseInt(input.readLine()));
                    if(new_profile.age > 0 && new_profile.age < 110) {
                        break;
                    }
                    throw new NumberFormatException("Out of bounds.");
                } catch(NumberFormatException nfe) {
                    output.print("Invalid response, try again: ");
                }
            }
            input.close();          
        } catch (IOException ioe) {
            output.println(ioe);
        } finally {
            output.close();
        }

        return new_profile;
    }

    @Override
    public String toString() {
        return String.format("Profile:\n  Name: %s %s\n  Age: %d\n", this.first_name, this.last_name, this.age);
    }
}

Issue 1: when I run this (Using the Eclipse IDE) the output I get is a blank terminal, where, once I enter a string, another string, and a valid integer, all one after the other in newlines, (then)the prompt lines where I do output.print(...) get printed. Here's an example to show what I mean:

first
last
20
Enter your first name: Enter your last name: Enter your age:

Issue 2: The line: output.print(hypro); won't get printed. Anything after the line Profile hypro = Profile.promptedProfile();.

So I'd like to ask:

  1. what's going on here (the conceptual knowledge about these io classes that I seem to be missing) ?
  2. what can I do to resolve these issues?

In advance, thank you.

P.S. I'm already aware of the java.util.Scanner class but I want to solve this issue without using it. Also, I'm open to suggestions about any better programming practices that I should have implemented here.

Let's start with a few basics:

First of all what does flushing of a stream means?, well, it simply means that when you flush a buffered stream, all the data from it is cleared off and sent to the target destination. In your code, flushing output would make sure that all the data in it is sent to the console (System.out) for printing.

Secondly the stream System.out is a STATIC stream, that is you get only one copy of that, and on closing it you can not use it again for printing things.

Issue 1:Now although you have enabled autoflushing (PrintWriter output = new PrintWriter(System.out, true); // the second argument is true), the autoflush is called only when \r\n (Carriage return line feed, CRLF) or a \n is encountered, and since your output statements miss those characters, none of the prompts get printed as the stream is not flushed at the correct times. The data keeps on appending to the stream until the end of the program when the autoflush finally runs for the first and the last time and, as a result, all the statements are printed in a line when the program terminates.

To fix: As explained in a previous answer, you can either use println() instead of print() or you can add the missing characters to the print() call like:

output.print(new_profile.getName() + "\r\n")

Or you can manually call flush() after each print() call (edit suggested by @EJP) if you'd like to get the outputs in the same line ๐Ÿ˜Š

Issue 2: As I just said, the System.out stream is a static one and since you close the stream when you call promptedProfile(), you can not use it again in your UsePrinterWriter class' main method. You can try printing something else before the function call like this:

output.println("foo bar"); //print something here Profile hypro = Profile.promptedProfile();

You will see that foo bar is printed on the console.

To fix: As in for fixing this issue, I'd say print everything in a single function and print everything before calling close() on a writer object that uses System.out, or you can simply use System.out.println(); to avoid all this altogether ;)

Java IO: PrintWriter, Java: Using BufferedReader and PrintWriter in Conjunction Causes Issues. Posted by: admin July 15, 2018 Leave a comment. Questions: I'm trying to learnย  Java: Using BufferedReader and PrintWriter in Conjunction Causes Issues How to invoke Explicit wait to click on the element with text as Login through Selenium and Java within the website https://www.phptravels.net

PrintWriter is buffered, and doesn't flush itself until either:

  1. You call flush(), or
  2. You constructed it with true for the autoflush argument and you printed a line terminator, either by calling println(), or by having \n or \r\n in the data passed to print() or write().

You aren't doing any of these things. If you want line-terminated output to appear immediately after print(), you need to flush.

BufferedWriter & PrintWriter ? (I/O and Streams forum at Coderanch), ) enables you to write formatted data to an underlying Writer . For instance, writing int , long and other primitive data formatted as text, rather than as their byte values. The issue is that the BufferedReader readLine() method requires an extra byte to show up at the end of a line that has a <CR> line ending before it will return the line. This has caused many hours of frustration trying to get some applets to work with the Mac platform.

  1. Don't use return statement for setters.
  2. You can open only one PrintWriter and pass that to your promptedProfile() method
  3. Use println(String str) method of PrintWriter to print to console
  4. Close the PrintWriter once everything is done.
  5. Use proper java variable convention
Try the below code and understand yourself.
import java.io.*;

public class UsingPrinterWriter {
    public static void main(String argv[]) {
        PrintWriter output = new PrintWriter(System.out, true);
        Profile hypro = Profile.promptedProfile(output);
        output.print("\n");
        output.flush();
        output.println(hypro);
        output.close();
    }
}

class Profile {
private String firstName;
private String lastName;
private int age;

Profile() {
}

Profile(String firstName, String lastName, int age) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
}

void setFirstName(String fn) {
    this.firstName = fn;

}

void setLastName(String ln) {
    this.firstName = ln;
}

void setAge(int a) {
    this.age = a;
}

static Profile promptedProfile(PrintWriter output) {
    Profile newProfile = new Profile();
    BufferedReader input = new BufferedReader(new InputStreamReader(System.in));

    try {
        // prompt for first name
        output.println("Enter your first name: ");
        output.flush();
        newProfile.setFirstName(input.readLine());

        // prompt for last name
        output.println("Enter your last name: ");
        output.flush();
        newProfile.setLastName(input.readLine());

        // prompt for age
        output.println("Enter your age: ");
        output.flush();
        while (true) {
            try {
                newProfile.setAge(Integer.parseInt(input.readLine()));
                if (newProfile.age > 0 && newProfile.age < 110) {
                    break;
                }
                throw new NumberFormatException("Out of bounds.");
            } catch (NumberFormatException nfe) {
                output.println("Invalid response, try again: ");
            }
        }
        input.close();
    } catch (IOException ioe) {
        output.println(ioe);
    }

    return newProfile;
}

@Override
public String toString() {
    return String.format("Profile:\n  Name: %s %s\n  Age: %d\n", this.firstName, this.lastName, this.age);
}
}

Java BufferedReader Class, write() method takes a single character, an array of characters, or a String. Problems with BufferedReader / PrintWriter? stackoverflow.com. I'm using BufferedReader and PrintWriter to go through each line of an input file, make a change to some lines, and output the result. If a line doesn't undergo a change,

What is the difference between BufferedReader and , What is the difference between BufferedReader and InputStreamReader in Java? #Use BufferedReader, BufferedWriter, File, FileReader, FileWriter, FileInputStream, FileOutputStream, ObjectOutputStream, ObjectInputStream, and PrintWriter in the java.io package. File This class is a representation of a file or a directory pathnames.

BufferedReader In Java | BufferedReader Class Examples, is an "abstraction" that reads text from a character-input stream. It "buffers" characters so as to provide efficient reading of characters and lines. marko spanovic added a comment - 2018-08-16 10:17 - edited Workaround is: def renderTemplate(input, binding) { def engine = new groovy.text.SimpleTemplateEngine() def template = engine.createTemplate(input).make(binding) def templateString = template.toString() engine = null template = null return templateString } So Jenkins doesn't caches those objects which are not serializable.

Why use BufferedReader and BufferedWriter Classses in Java, This article covers the BufferedReader in Java from the Reader class along with It inherits the reader class and makes the code efficient since we can read the data There are a lot of problems with the nextline() method. Microsoft Sharepoint 2013 : The Ultimate Enterprise Collaboration Platform. Java: Using BufferedReader and PrintWriter in Conjunction Causes Issues Tags ajax android angular api button c++ class database date dynamic exception file function html http image input java javascript jquery json laravel list mysql object oop ph php phplaravel phpmysql phpphp post python sed select spring sql string text time url view windows

Comments
  • You seem to be creating multiple outputs, when you need zero since there's already System.out that you should be using. It's hard to follow the code when it's filled with unnecessary things. Basically your problem probably stems from creating those wrappers and they all share the System.in and out that you should be using. You can create a BufferedReader for reading input, but you don't need to do anything for output. Only create one and share that.
  • @Kayaman, in the book, Herbert Schildt says: "There is nothing wrong with using System.out to write simple text output to the console when you are learning Java or debugging your programs. However using a PrintWriter will make your real-world applications easier to internationalize. " (since it's a character stream and not a byte stream). This is why I'm insisting on using the seemingly unnecessary PrintWriter instances. I have used BufferedReader before in conjunction with System.out directly and have not faced issues. But That's not what I'm trying to do here.
  • Well, real world applications don't really print to the console anymore, so the book's age is showing. Still, I'm sure the book doesn't say "create a new PrintWriter everywhere". You can wrap in and out, but if you do, do it once. The book might be a bad fit for you too, it seems to be a "quick reference".
  • @Kayaman yeah, the book mentioned that " real world applications don't really print to the console anymore" and you're right, it's more of a quick reference I guess. Anyhow I realized my mistake: When we chain input or output streams (i.e. wrap them around each other) closing the outer stream will automatically close the inner streams as well. I guess that's what I needed to know (for issue 2 anyhow).
  • OP may not want line-terminated output for his prompts. There is another solution.
  • @EJP Well, all that I had in mind while writing the answer was the flush() call, (don't know how I forgot that,) so I don't know if there is another solution that you were talking about, would be glad if you could tell us about it๐Ÿ˜ And thank you for pointing it out man! ๐Ÿ˜Š
  • You haven't actually explained anything here, and the OP did ask for 'conceptual knowledge': and several of your recommendations are off. Closing the PrintWriter would also close System.out, which is undesirable in general; and the OP may not want line-terminated output for his prompts.
  • Your edits are all futile. All they do is (1) add extra line terminators and (2) call flush() when it isn't needed. And there is still no explanation here.