Java views each file as a sequential stream of bytes. When a file is opened, an object is created and a stream is associated with the object. The streams provide communication channels between a program and a particular file or device. Object System.in (standard input stream object) enables a program to input bytes from the keyboard, object System.out (standard output stream object) enables a program to output data to the screen, and object System.err (standard error stream object) enables a program to output error messages to the screen. System.out can be redirected to send its output to a file. By convention, System.err stream is used to display error messages.
The java package java.io provides standard library classes to deal with streams. Classes in the package are divided into input and output streams, and then subdivided into those, which operate with characters data (text files) and with byte data (binary files).
The difference between a stream of characters from a stream of bytes is that the former uses Unicode characters, which are represented by 16 bits - that is it, in java, a character is made up of two bytes. In contrary, the C language uses 1 byte characters (ASCII table). The natural question to ask is how Java deals with these encoding problems: converting bytes to characters and back. The Java has different tables of encoding and you can choose any of them. To see the default table you print
System.getProperty("file.encoding");
System.out.print()
and System.out.println()
. The printf()
method gives us
more
control over the output. Compare
System.out.println(Math.PI); System.out.printf("%7.5f", Math.PI);
"%7.5f"
is a format that describes how the
second
argument is to be printed. This format says, that we print a float number of 7 characters
that
includes 5 digits after the decimal point.
java
command to invoke a Java program
Demo
from the command line, you type something like this
java Demo parameter1 parameter2
Input values parameter1
and parameter2
are passed to a
main()
method as an array of Strings.
int n = Integer.parseInt(args[0]); double sum = 0.0; Scanner scanner = new Scanner(System.in); //it's defined in java.util for(int k = 0; k < n; k++) sum += scanner.nextInt(); System.out.println("Average = " + sum/n);
java Average 4
java Average 4 > out.txt
out.txt
. Similarly, we can redirect standard input so that a program reads data from a file
instead of the terminal application. For example,
java Average 4 < input.txt
input.txt
and prints their average to
the terminal window. We can redirect the ouput to and from a file in one command line
java Average 4 < input.txt > out.txt
Exceptions in the object-oriented language is a quite complex topic that requires time to understand and apply properly. By now you perhaps met a few exception classes such as the following
NullPointerException
ArrayIndexOutOfBoundsException
ArithmeticException
NullPointerException
Here are three examples demonstrating what causes the NullPointerException:
String str = null; int n = str.length(); String[] data = new String[10]; int k = data[5].length(); String s = null; StringBuffer sb = new StringBuffer(s);
All exceptions are objects. Once an exception is thrown you have three options:
Consider this code segment in which a user is prompted to enter an integer:
Scanner scanner = new Scanner(System.in); int m = scanner.nextInt();
nextInt()
method will throw InputMismatchException
.
That is your responsibility (as a programmer) to validate the input. One way to do this is to handle exceptions, meaning that you have to catch exceptions.
Scanner scanner = new Scanner(System.in); System.out.print("Enter an integer: "); try { int n = scanner.nextInt(); System.out.println("You entered " + n); } catch (InputMismatchException e) { System.out.println("The input is not an integer"); }
Review the code example ExceptionDemo.java class.
It's common to test parameters of methods or constructors for valid input data. If the value is illegal, you throw an exception by using the throw
keyword along with the object you want to throw. Examine this code example
public Card(int suit, int value) { if (isValidValue(value) && isValidSuit(suit)) { this.value = value; this.suit = suit; } else throw new RuntimeException("Illegal suit or value"); }
Throw behaves similar to return, it performs structured transfer from the place in your program where an abnormal condition was detected to a place where it can be handled. It also transmits information. The exception object may contain a detail message that can be retrieved by invoking the getMessage() method
Any method that may throw an exception, must declare the exception in it's method declaration. This is implemented by the use of the throws
clause. Throws clause follows the method name and lists the exception types that may be thrown:
public static main(String[ ] args) throws IOException { }
The throws
clause is used
Developer | Client | |
Method body | Throw the exception | Use a try/catch block |
Method header | Declare the exception | Propagate the exception |
Java distinguishes checked and unchecked exceptions. A checked exception means that if you ignore it, your program will not compile. What do you do in this case? Either you use try-catch blocks or propagete the exception usingh throws clause.
There are two approaches of reading text files:
I II classes: FileReader Scanner BufferedReader File exceptions: FileNotFoundException FileNotFoundException IOException IOException methods: readLine println close close
The FileReader
class represents an input file that contains character data. The
class throws FileNotFoundException
(checked exception), so you have to wrap try
and catch block around each time you open a file. For the efficient reading, we use the
BufferedReader
class. It provides the method readLine()
that allows to read the entire text line (a line is a sequence of characters terminated either by '\n' or '\r' or their combination). The method returns a String, or null if the end of the stream has been reached. The readLine() method throws IOException
, so you have to handle it.
A text file can also be read using the Scanner
class. Using the Scanner offers the advantage for text processing of various data formats.. Scanner has a lot of other features, with support for regular expressions, delimiter definitions, skipping input, searching in a line, reading from different inputs and others..
Review the code examples Read.java and ReadHTML.java
writing classes: FileWriter BufferdWriter PrintWriter exceptions: IOException methods: println close
The FileWriter class represents an output file that contains character data. It throws IOException. The class has minimal method support, like a method write , which writes a character or an array of characters or String. Unless prompt output is required, it is advisable to wrap a BufferedWriter around for efficiency reason. The class has the newLine() method, which uses the platform's own notion of line separator. Neither FileWriter nor BufferedWriter provides enough methods to deal with a formatted output. For such purposes we shall use another class PrintWriter on the top of the previous two classes. The class uses familiar methods print and println.
Review the code example Write.java
"\n"
, on Windows - "\r\n"
, and on Mac - "\r"
. In Java the line separator is defined by the system property line.separator
, which should be called as it follows
String out = "any characters"; out += System.getProperty("line.separator");
FileWriter
has a second argument, which is boolean, indicating
whether or not to append the data written. Here is a code fragment,
BufferedWriter out = new BufferedWriter (new FileWriter("out.txt", true));
FileOutputStream out = new FileOutputStream("output.ser"); ObjectOutputStream outStream = new ObjectOutputStream(out);
and then use a method writeObject()
to write an object into a file in a
binary format. It throws IOException
and NotSerializableException
.
outStream.writeObject("Today"); outStream.writeObject(new Date()); outStream.flush();
You can write primitive data types as well. They are written to the stream with the
methods, such as writeInt
, writeFloat
, and a few others.
The class of each serializable object is encoded including the class name and
signature of the class, the values of the object's fields and arrays, and the closure
of any other objects referenced from the initial objects. Only objects with the Serializable
interface can be serialized. The
interface does not have any methods, and serves only as a flag to the compiler. For most
classes the default serialization is sufficient. Many classes of API implement
Serializable
interface, for example String, Vector.
Reading an object from a stream, like writing, is straightforward. To reverse the process, we first create an input stream,
FileInputStream in = new FileInputStream ("output.ser"); ObjectInputStream inStream = new ObjectInputStream(inStream);
readObject()
method to read the information from "output.dat"
file.
String today = (String) inStream.readObject(); Date date = (Date) inStream.readObject();
ClassNotFoundException
and IOException
checked exceptions. Primitive data types are read from the stream with the methods, such
as readInt, readFloat
.
The default serialization process serializes each field of the object except
static
and transient
. Using transient
, we can exclude
particular information when we serialize the oblect. An example of such excluded
information could be a password.
Review the code example SerializationDemo.java