This course has already ended.

Java input and output streams

A Java virtual machine (JVM) automatically initializes the output objects System.out and System.err and the input object System.in as public member class variables of the class System. These have similar roles as e.g. the C++ stream objects cout, cerr and cin. System.out prints to the standard output (e.g screen), System.err to the standard error output (e.g. screen), and System.in reads from the standard input (e.g. keyboard).

To be more precise, System.out and System.err are objects of the class java.io.PrintStream. The most commonly used printing functions of this class are probably println and print, which print out a single value given to them as a parameter. The functions automatically convert a non-string parameter into a String. The only difference betweeen the two functions is that println prints out a new line after the value and println can also be called without a parameter (it will then print a single new line). A third quite commonly used printing function is format, which is a Java counterpart of the C function printf. Note that also Python’s counterpart to printf is named format. PrintStream does in fact contain also a function named printf, but it is identical with format and we have chosen to use this latter function name in this material.

The format function takes a so-called “format string” parameter that allows to embed variable values into the printed string. The format string is a String that is otherwise printed as such, but it may contain special format specifiers that start with the percent character ‘%’. The format specifiers (usually) specify that format should replace the specifier with the value of a corresponding separately provided function parameter. This implies that such replacing parameters must be given to printf as further parameters after the format string. Each specifier defines the type of the replacing value. For example %s means a string, %d an integer and %f a floating point value. Format specifiers can also contain further formatting modifiers that e.g. define a width or precision to use when embedding that particular value. Basic examples are given below. See the documentation of Formatter for further details about available specifiers and formatting parameters.

String name = "Lionel Messi"
int birthYear = 1987;
double height = 1.69;
System.out.format("Name: %s, Birth year: %d, Height: %.2f%n", name, birthYear, height);
System.out.format("Pi with three decimals and 10-character width: %10.3f", Math.PI);

Here e.g the specifier “%.2f” means a floating point value printed with two decimals, and “%10.3f” a floating point value printed with three decimals and width of 10-characters (padded with spaces). In addition the specifier “%n” means a system specific new line: for example “n” on Linux and “rn” on Windows. The code snippet would print:

Name: Lionel Messi, Birth year: 1987, Height: 1.69
Pi with three decimals:      3.142

The PrintStream class can also be used for printing into files: if we give a string as a constructor parameter when creating a new PrintStream object, the resulting object will print into a file named by the string parameter. Note that if the file already exists, its previous contents will be overwritten. If we want to avoid that, we need to first create a java.io.FileOutputStream file outputstream object in append mode and then use that object (instead of a string) as the PrintStream constructor parameter.

System.in is an object of class java.io.InputStream. InputStream is an abstract input stream class that is suited for quite basic bytewise input operations. The class java.io.BufferedReader provides more convenient operations for reading text data, such as the member function readLine that reads a single input line. In order to use BufferedReader, we must first create an unbuffered input stream object and then give it as a constructor parameter for BufferedReader. The class java.io.InputStreamReader provides unbuffered reading operations from an input stream that can be specified as a constructor parameter.

To sum up the preceding, we could for example construct a BufferedReader object for reading standard input as follows: new BufferedReader(new InputStreamReader(System.in)). This kind of a layered construct InputStreamInputStreamReaderBufferedReader might especially at first feel cumbersome, but this kind of constructs are very common in Java (and quite common elsewhere, too).

BufferedReader is convenient also for reading files. The only difference to the preceding example is that we should provide the constructor of BufferedReader with an unbuffered file input stream object. This can be created easily using the class java.io.FileReader that accepts the name of the file to read as a constructor parameter.

Using streams ⇒ usually need to consider exceptions

An error during an input or output stream operation, e.g. failing to open a file, can cause a so-called exception. We will discuss exceptions later, but at this point it is worth mentioning that Java in many cases requires us to somehow consider the possibility of such exceptions: otherwise the Java compiler will give an error. Unless we implement an explicit exception handler ourself, the exception will propagate from the current function to its caller. In order to help the caller anticipate such a possibility, a Java function definition must explicitly list the kind of exceptions that can propagate out from the function. This kind of so-called exception specification is given at the end of the function header in the form “throws exceptionType1, ..., exceptionTypeN”. That is, the keyword throws followed by a list of exception types separated by commas. Java stream operations usually cause (or throw) exceptions of type IOException.

The preceding rule does not apply to all exceptions. Java exceptions have been divided into two broad categories: checked and unchecked exceptions. Only checked exceptions must be either handled explicitly or declared in an exception specification.

Full featured IDE’s (e.g. Netbeans) will automatically inform you about the types of checked exceptions that may occur in your code. You can also find that information by browsing the documentation of the libraries used in your code, or as a last resort, from error messages given by the Java compiler.

Files should be closed once you no longer need to access them. This can be done explicitly by calling the member function close of the stream object. A more recommended way is to use Java’s so-called “try-with-resources” structure, which will automatically close the file. Note that also Python contains a similar mechanism.

Below is an example program that illustrates stream input and output. The program first reads an input filename, line length limit and output filename from the standard input (ie. from keyboard). The program will then read the input file and write its contents to the output file in such manner that all words as separated with single spaces and no line is longer than the specified line length. The program stops when the user enters “quit”, and otherwise the program will proceed to again ask the user to give an input filenane, line length limit and an output filename.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;

public class LineWrap {

  // The stream operations in the main function may cause an exception of type
  // IOException. Therefore we have added an exception specification
  // "throws IOException" to the end of its header.
  public static void main(String args[]) throws IOException {
    // Create a BufferedReader object "user" for reading System.in.
    // Note that, unlike with files, we should not use try-with-resources here
    // because the standard input stream should not be closed.
    BufferedReader user = new BufferedReader(new InputStreamReader(System.in));
    while(true) {  // An infinite loop that will be exited upon a "quit" command.
      System.out.print("Give input filename (or 'quit'): ");
      final String inputFilename = user.readLine();
      if("quit".equalsIgnoreCase(inputFilename)) {
        break;
      }
      System.out.print("Give line wrap length limit (or 'quit'): ");
      String lineLimStr = user.readLine();
      if("quit".equalsIgnoreCase(lineLimStr)) {
        break;
      }
      final int lineLim = Integer.parseInt(lineLimStr);
      System.out.print("Give output filename (or 'quit'): ");
      final String outputFilename = user.readLine();
      if("quit".equalsIgnoreCase(inputFilename)) {
        break;
      }

      // Also count statistics about input and output lines.
      int inputLines = 0;
      int outputLines = 0;

      // The form of try-with-resources:
      //   try(resource variable statements separated by semicolons) {
      //     the code block that uses the resources
      //   }
      // The resources listed by the resource variable statements will be closed
      // automatically when the program exits the following code block. The resources
      // must have a member function "close". In try-with-resources below we create
      // BufferedReader input for file reading and PrintStream output for file writing.
      // This is also an example where using the inferred var type might be ok: the
      // conrete type has a longish name and is anyway spelled out in the new operation.
      try(var input = new BufferedReader(new FileReader(inputFilename));
          var output = new PrintStream(outputFilename)) {
        String line = null;
        int lineLen = 0;
        while((line = input.readLine()) != null) {
          inputLines += 1;
          // Split interprets its parameter as a regular expression, where "\\s+"
          // means one or more space characters (space, tabulator, etc.).
          String[] words = line.split("\\s+");
          for(String word : words) {
            if(word.length() > 0) {
              if(lineLen > 0 && lineLen + 1 + word.length() > lineLim) {
                output.println();
                outputLines += 1;
                lineLen = 0;
              }
              if(lineLen > 0) {
                output.print(" ");
                lineLen += 1;
              }
              output.print(word);
              lineLen += word.length();
            }
          }
        }
        if(lineLen > 0) {
          output.println();
          outputLines += 1;
        }
      }
      // At this point input and output have been closed automatically.
      // Print out input and output line statistics. This time as an example to System.err.
      System.err.format("The input file %s had %d lines.%n", inputFilename, inputLines);
      System.err.format("The wrapped file %s has %d lines.%n", outputFilename, outputLines);
    }
  }
}

You want to print the following data: String author = William Shakespeare; String title = Othello; integer published = 1603; Which of the following prints it in the format: Author: William Shakespeare, Title: Othello, First performance: 1604

You have double[] temperatures that contains temperature readings from a tropical greenhouse. Which of the following prints an element from it in three decimals on a line of its own inside the loop for(double d : temperatures) {}:

Posting submission...