CodeGym/Java Blog/Java IO & NIO/Java PrintStream Class
Author
Vasyl Malik
Senior Java Developer at CodeGym

Java PrintStream Class

Published in the Java IO & NIO group
members
Hi! Today we'll talk about the Java PrintStream class and everything it can do.  Actually, you are already familiar with two methods of the PrintStream class. They are print() and println(), which you probably use every day :) Because the System.out variable is a PrintStream object, you are calling one of this class's methods when you call System.out.println().  The general purpose of the PrintStream class is to send information to some stream. Why we need the PrintStream class - 1 This class has several constructors. Here are some of the most commonly used:
  • PrintStream(OutputStream outputStream)
  • PrintStream(File outputFile) throws FileNotFoundException
  • PrintStream(String outputFileName) throws FileNotFoundException
For example, we can pass the name of the output file to the PrintStream constructor. Alternatively, we can pass a File object. Let's look at some examples to see how this works:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;

public class Main {

   public static void main(String arr[]) throws FileNotFoundException
   {
       PrintStream filePrintStream = new PrintStream(new File("C:\\Users\\Username\\Desktop\\test.txt"));

       filePrintStream.println(222);
       filePrintStream.println("Hello world");
       filePrintStream.println(false);

   }
}
This code will create a test.txt file on the desktop (if it doesn't already exist) and sequentially write our number, string, and boolean to it. Here are the file contents after we run the program:

222 
Hello world!
false
As we said above, you don't have to pass a File object. It's enough to simply pass the file path to the constructor:
import java.io.FileNotFoundException;
import java.io.PrintStream;

public class Main {

   public static void main(String arr[]) throws FileNotFoundException
   {
       PrintStream filePrintStream = new PrintStream("C:\\Users\\Username\\Desktop\\test.txt");

       filePrintStream.println(222);
       filePrintStream.println("Hello world");
       filePrintStream.println(false);
   }
}
This code does the same as the previous code. Another interesting method worth our attention is printf(), which produces output based on a format string. What is a "format string"? Let me give an example:
import java.io.IOException;
import java.io.PrintStream;

public class Main {

   public static void main(String[] args) throws IOException {

       PrintStream printStream = new PrintStream("C:\\Users\\Steve\\Desktop\\test.txt");

       printStream.println("Hello!");
       printStream.println("I'm a robot!");

       printStream.printf("My name is %s. I am %d!", "Amigo", 18);

       printStream.close();
   }
}
Here, instead of explicitly stating our robot's name and age in the string, we put placeholders for this information, represented by %s and %d. And we pass as arguments the data that will replace them. In our case, this is the string "Amigo" and the number 18. We could create another placeholder, say %b, and pass another argument. Why do we need this? Above all, for greater flexibility. If your program requires you to display a welcome message often, you would have to manually type out the necessary text for each new robot. You can't even make this text a constant, since everyone has different names and ages! But using this new method, you can isolate the greeting in a constant and, if necessary, simply change the arguments passed to the printf() method.
import java.io.IOException;
import java.io.PrintStream;

public class Main {

   private static final String GREETINGS_MESSAGE = "My name is %s. I am %d!";

   public static void main(String[] args) throws IOException {

       PrintStream printStream = new PrintStream("C:\\Users\\Steve\\Desktop\\test.txt");

       printStream.println("Hello!");
       printStream.println("We are robots!");


       printStream.printf(GREETINGS_MESSAGE, "Amigo", 18);
       printStream.printf(GREETINGS_MESSAGE, "R2-D2", 35);
       printStream.printf(GREETINGS_MESSAGE, "C-3PO", 35);

       printStream.close();
   }
}

Replacing System.in

In this lesson, we will "fight the system" and learn how to replace the System.in variable in order to redirect system output to wherever we want. You might forget what System.in is, but no CodeGym student will ever forget this construct:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.in  (just like System.out) is a static variable of the System class. But unlike System.out, it references another class, namely InputStream. By default, System.in is a stream that reads data from a system device — the keyboard. However, just as with System.out, we can replace the keyboard as the data source. We can read data from wherever we want! Let's look at an example:
import java.io.*;

public class Main {

   public static void main(String[] args) throws IOException {

       String greetings = "Hi! My name is Amigo!\nI'm learning Java on the CodeGym website.\nOne day I will become a cool programmer!\n";
       byte[] bytes = greetings.getBytes();

       InputStream inputStream = new ByteArrayInputStream(bytes);

       System.setIn(inputStream);

       BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

       String str;

       while ((str = reader.readLine())!= null) {

           System.out.println(str);
       }

   }
}
So what did we do? System.in is usually bound to the keyboard. But we don't want to read data from the keyboard: let's have the data be read from an ordinary string! We created a string and got it as a byte array. Why do we need bytes? The thing is that InputStream is an abstract class, so we can't create an instance of it directly. We have to choose one of its descendants. For example, we can choose ByteArrayInputStream. It is simple, and its name alone tells us how it works: its data source is a byte array. So we create a byte array and pass it to the constructor of our stream that will read the data. And now everything is ready! Now we just need to use the System.setIn() method to explicitly set the value of the in variable. With out, you will recall, it was also not possible to set the variable's value directly: we had to use the setOut() method. After we assign our InputStream to the System.in variable, we want to check whether we have achieved our purpose. Our old friend BufferedReader comes to our aid here. Normally, this code would have opened the console in IntelliJ IDEA and then read data you entered from the keyboard.
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

       String str;

       while ((str = reader.readLine())!= null) {

           System.out.println(str);
       }
But now when you run it, you will see that our string is simply displayed in the console. There is no reading from the keyboard. We replaced the data source. It is no longer the keyboard, but our string! It's that simple :) In today's lesson, we got to know a new class and explored a small new hack for working with I/O. Now it's time to return to the course and complete some tasks :) See you in the next lesson!
Comments (20)
  • Popular
  • New
  • Old
You must be signed in to leave a comment
claudia
Level 19 , Germany, Germany
20 November 2023, 10:36
Ist "String arr[]" in main dasselbe wie "String[] args"?
Mike S
Level 28 , Saint Louis, United States
7 February 2023, 19:32
The most confusing thing here to me is the difference between writing some piece of text to a file and printing to it. Maybe there is no difference on the surface...
Aldo Luna Bueno
Level 28 , Peru
23 March 2022, 16:46
Intersting. How could this input change be reversed?
Hoa Nguyen
Level 15 , Australia
Expert
17 February 2022, 05:25
Such a clear explanation!! thank you!
Ryan Palmer
Level 20 , Philadelphia, United States
9 August 2021, 03:39
This really cleared up a lot of confusion. I'd recommend reading this before some of the exercises - if you stumble upon it.
Andrei
Level 41
18 January 2021, 09:32
Very nice article, made things much clearer.
Chandan Thapa
Level 22 , Dubai, United Arab Emirates
30 December 2020, 08:47
just a quick thought on the last topic - Replacing System.in - i get that we can modify the existing function in the class and it works as per we need. but whats the purpose of this? do we need to do this when we start working at our jobs and if yes then where are its applications? some clarity would be great!
Andrei
Level 41
18 January 2021, 09:32
Good question!
Sansho
Level 19 , Bordeaux, France
25 June 2021, 13:02
Do you guys have the answer now? :)
Andrei
Level 41
25 June 2021, 13:40
Not yet, haven't worked with System.in - out since then, tbh :)
Gellert Varga
Level 23 , Szekesfehervar, Hungary
2 July 2021, 23:03
I compiled it from comments from fellow students: We can swap the default meaning of System.in input stream for something else. With the purpose to a ready-made program that would expect input from the keyboard can be able to get the expected data from somewhere else. You should not have to press the keyboard all the time. It can be very useful when you need to test a program many times. Anywhere in the program where you have System.in data entry, it will immediately read the data you compiled - from the source you defined.
Hoist
Level 32 , San Diego, United States
24 January 2023, 21:04
Your comments -- and further explainers -- provide a major contribution to Code Gym being a better platform for Java.
Agent Smith
Level 38
6 September 2020, 15:50
No CodeGym student will ever forget this construct:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Indeed. :D
Sansho
Level 19 , Bordeaux, France
25 June 2021, 13:03
#Team Scanner sc = new Scanner(System.in);
BlueJavaBanana
Level 37
28 May 2020, 11:12
I'm unsure what this means: Because the System.out variable is a PrintStream object, you are calling one of this class's methods when you call System.out.println().  Can anyone clear this up/explain in a different way?
Daniel Walbolt
Level 22 , Waterville, United States
21 July 2020, 11:04
This is obviously a bit late of a response, but just as you have worked with variables and methods before, this works in the same way. Solution.print() is a call to a method in the Solution class. System.out.println() is a call to the println() method in the System.out class.
BlueJavaBanana
Level 37
21 July 2020, 12:12
Cheers for the reply.
Gellert Varga
Level 23 , Szekesfehervar, Hungary
2 July 2021, 23:38
The out is a reference-variable in the System class, but it is actually an object of the PrintStream class. So you can run the usual PrintStream methods on the object named 'out' : write(int), flush(), etc. (Not only the much used println() method works on it!) Try this program:
public class TestOut {
    public static void main(String args[]) throws Exception {

      System.out.write(65); // writing the code of 'A' into the stream
      System.out.write(66); // code of 'B'
      System.out.write(67); // code of 'C'

          Thread.sleep(2000);

      // Now the text "ABC" is displayed on the console:
      System.out.flush(); // you can use here the close() method, too
    }
}
First you write the bytes into the stream, then the program waits 2sec, and when you call the flush() method or the close() method, the stream forces the accumulated data out to the stream's endpoint, which is now the console. = the "ABC" text is displayed. Even though we didn't even use the usual System.out.print() method.:)
Oregano
Level 24 , Warsaw, Poland
16 May 2020, 11:37
"For example, we can choose ByteArrayOutputStream. It is simple, and its name alone tells us how it works: its data source is a byte array. Shouldn't it be ByteArrayInputStream?
Gellert Varga
Level 23 , Szekesfehervar, Hungary
3 July 2021, 15:49
This bug has been fixed by CodeGym today. In case of such a mistake, you also can tell this directly to a CG staff:) and they will fix it.