15-100 Lecture 6 (Monday, September 12, 2005)

Quick Quiz

  // Write a method that divides two double-precision numbers, returning
  // the result, also as a double-precision number
  public static double divideDouble (double number1, double number2) {
    return (number1/number2);
  }
  

Java Input/Output

Think of the java input and output system like a producer consumer relationship, you can only do one thing at a time. Either you can consume the item of produce the item, you can’t be both producing and consuming an item at the same time. Java works a lot like that, it can only be either inputting or outputting at a given time.

The most basic part of Java IO is the ‘System’. The System represents the machine. Thus, System.in represents an input stream coming into the machine. Unfortunately this input stream is very rudimentary and just reads the information in byte by byte. Since it would be difficult to be able to manipulate the data in this form Java has some additional classes that you can use to manipulate the data stream. The next level up that we’re going to use is the InputStreamReader. InputStreamReader is passed System.in, and creates an input stream that will return characters instead of just bytes. So far the code that we have is:

InputStreamReader isr  = new InputStreamReader(System.in);

Obviously it is easier to manipulate entire characters instead of just bytes, but we want to be able to access more then just one character at a time. Because of this Java provided the BufferedReader. BufferedReader is passed an InputStreamReader, which it uses to read an input stream character by character into a buffer, until it has read an entire line. Once it has read a line it will return the entire line to the user. So far the code is:

  InputStreamReader isr = new InputStreamReader(System.in);
  BufferedReader br = new BufferedReader(isr);
  String s = br.readLine( );
  

This means that program will go until it reaches the ‘String s = br.readLine()’ line at which point it will wait for the user to enter a line of text and then it will go and read the line. So lets now make these lines actually do something.

  InputStreamReader isr = new InputStreamReader(System.in);
  BufferedReader br = new BufferedReader(isr);
  System.out.print("What's your name? ");
  String s = br.readLine();
  

This gives the user a prompt, asking them for their name, which the program reads, once it has been entered. There is one problem with this section of code though. Printing may be delayed because output is actually a give and take between program and operating system. So what may happen if the operating system buffer isn’t full then it may wait until it is to print this out on the screen. But, now the program is waiting for a String to be input into the computer, and the user doesn't see a prompt to tell them that they need to enter input. So now computer is waiting for user and user is waiting for computer; this creates a dilemma, because the computer is now hung.

There is a way to fix this. In situations like this you have to tell the computer to flush its buffer before the program reads the line. In order to do this you use the System.out.flush() command. The correct code is below.

  InputStreamReader isr = new InputStreamReader(System.in);
  BufferedReader br = new BufferedReader(isr);
  System.out.print("What's your name? ");
  System.out.flush();
  String s = br.readLine();
  

There is one last important thing to remember when using Java IO, that is the location in you're program that you add it. You're goal as a programmer is to create good code that is easy to reuse, and will require little maintenance if you ever need to update it. Unfortunately, many applications of Java use many different types of IO. Since, you want your Java classes to be able to be used across many different applications it is important to keep the IO in the user interface, thus when you get to a new application only the user interface changes, not the entire class. There can be occasional exceptions for when the IO information needs to be inside a particular method, but for the most part points will be deducted for putting the IO information in the wrong method.

One More Example

This example reads in someones name, then prints says hello. First put "import java.io.*" at the top of the file, as the very first line.

  import java.io.*;
  public static void main(....) throws Exception {
    InputStreamReader isr = new InputStreamReader(System.in);
    BufferedReader br = new BufferedReader(isr);

    System.out.print("What is your name?");
    System.out.flush();
    String name = br.readLine();

    System.out.println("Hello, "+ name)
  }
  

Java Primitive Data Types and Wrapper Classes

Now that you are able to read Strings into you're program you'll want to be able to convert them to useful things, like ints and floats, that you used in the textbook class. First, lets review the six primitive data classes:

Each of these primitive data types has a class called a "wrapper" class. By Java convention the name of each of their wrapper classes is just the full name of the data type with the first letter capitalized. We'll talk more a bit later about why these classes are called "wrapper" classes. The six wrapper classes are listed below.

Let's consider the Integer class. It contains a static method, "parseInt" that functions as below:

  String numberString = "1234";
  int number;

  number = Integer.parseInt (numberString);
  

As you can see, this method can convert the String representation of an int into a genuine int. The other wrapper classes have similar methods:

So, what happens if you pass in a String that can't be converted? For example, "Float.parseFloat("abcd")" or "Integer.parseInt ("123.456")". This is obviously an error. The conversion can't be completed. When this is encountered, Java "throws an Exception". This means that it kicks the program into a special error-handling mode.

We'll talk more about how to make use of that mode later. But, for now, let's just observe that any method using these methods, and any method using those methods, and so on, should add the "throws Exception" clause to its declaration:

  public static void main (String[] args) throws Exception { ...}
  

This clause just admits that an exception can be thrown, causing the program to end.