
Java’s Hierarchy Input/Output Classes and
Their Purpose

These slides introduce several input and output
classes for special purposes, such as reading or
writing a file.
Some of these slides use the concept of inheritance.
.

Data is text
(characters and
String)
Data in binary format
Sequential Access
write to terminal
text, html files
printf( ), format( )
not human readable
efficient for space
and computer read
image, MP3, Word
Random Access

A file stores information or data as bytes.
We can store anything:
An editor stores text. characters are translated to
bytes.
Can be 1 character = 1 byte or 1 char = 2 bytes ...
Example: Eclipse stores Java src code as text
Other applications store binary data.
Example: MP3, JPEG, PNG

InputStream read input as bytes
Reader read input as characters
InputStreamReader
BufferedReader read Strings, read entire lines

buffer = new StringBuffer( );
while ( true ) {
int c = inputStream.read( );
if ( c < 0 ) break; // end of input
buffer.append( (char)c );
}
Reads input as bytes -- one byte (or array) at a time.
Useful for reading data in binary format.
!""
buffer = new StringBuffer( );
int c = 0;
while ( (c=inputStream.read( )) >=0 ) {
buffer.append( (char)c );
}
This kind of code is common in C.
#$
byte [] buff = new byte[80];
while ( true ) {
int count = inputStream.read( buff );
if ( count <= 0 ) break; // end
// process the bytes in buff
}
It is more efficient to read many bytes at one time.

An InputStream connected to a file.
Has many constructors.
Works just like InputStream!
FileInputStream inputStream =
new FileInputStream("c:/test.dat");
while ( true ) {
int c = inputStream.read( );
if ( c < 0 ) break; // end of input
buffer.append( (char)c );
}
inputStream.close( );
%
Each layer "adapts" a lower layer to provide a different
interface. They are adaptors.
InputStream
read bytes
Reader
read chars
BufferedReader
read Strings
Scanner
read and
convert to
many types

InputStream reads bytes and returns them.
No interpretation of character sets.
OK for binary data.
Not good for character data using character set.



&'''(
$
$&')*(
$
&')$+,$*(

$-
.
Reader: reads bytes and converts to characters.
Interpret bytes using a Character Set Encoding.
Can handle any language... if you know the charset.



.&
#.)
'/012340*(
"
&')*(
"
&')+,
*(
.
$-


.
InputStreamReader is a kind of Reader.
It reads the input and returns characters.
InputStream in = new FileInputStream( "test" );
InputStreamReader reader =
new InputStreamReader(in);
// read a character
char b = (char) reader.read( );
// read several characters
char [ ] buff = new char[100];
int nchars = reader.read( buff, 0, 100);
// close the input stream
reader.close( );

Java API docs list names of character sets.
InputStreamReader reader
= new InputStreamReader( inputStream, "charset" );
Charset Name Description
ASCII ASCII 7-bit encoding
ISO8859_1 ISO 8859-1 Latin alphabet No. 1
Cp874 IBM (DOS) Thai encoding
MS874 MS Windows Thai encoding
TIS620 TIS-620, Thai encoding
UTF-8 8-bit UTF encoding
UTF-16 16-bit UTF encoding
5.
BufferedReader reads input as Strings.
It uses a Reader to read characters
BufferedReader breader = new BufferedReader(
new InputStreamReader( System.in ) );
// read a line
String s = breader.readLine( );
Buffered Reader methods:
int read( ) - read next char
int read(char[ ], start, count) - read chars into array
String readLine( ) - return a string containing rest of the line
close( ) - close the reader
5.
To read from a file, create a BufferedReader around a FileReader.
The ready() method returns true if (a) input buffer contains data
(e.g. reading from System.in or a pipe) or (b) underlying data source
is not empty (reading from file).
BufferedReader bin = new BufferedReader(
new FileReader( "mydata.txt" ) );
// read some lines
while( bin.ready( ) )
{
String s = bin.readLine( );
// do something with the string
}
bin.close( );
.
Java has a Reader class corresponding to common InputStream
classes.
InputStream Reader
InputStream InputStreamReader
LineNumberInputStream LineNumberReader
FilterInputStream FilterReader
FileInputStream FileReader
PipedInputStream PipedReader
Reading Binary Data
DataInputStream use readChar() method
of DataInputStream to
interpret data as characters
%
Java provides a hierarchy of classes for processing input
from different sources and types.
Java Input Stream Class Hierarachy
InputStream
ByteArrayInputStream
FileInputStream
PipedInputStream
ObjectInputStream
SequenceInputStream
FilterInputStream
DataInputStream (binary input)
BufferedInputStream
LineNumberInputStream
PushbackInputStream
These are
"wrappers"
for another
input stream.
%#.#6"
InputStream has an available( ) method that returns
the number of bytes waiting to be read.
Use this to read without blocking.
Reader classes have a ready() method.
InputStream in = System.in; // or whatever
// read whatever bytes are available
int size = in.available();
if ( size > 0 ) {
byte [ ] b = new byte[size];
in.read( b ); // this should not block
}
5.788 
The readLine( ) method returns null if the end of input stream
is encountered. You can use this to read all data from a file.
"9&0':0(
5.$&#5.)
#.)9**(

"(
#))&$';)**<&*
=
"
'')'>)**(
?
9')*(
.%
." 
Examples:
MP3 file, image file
Advantages:
space efficient, can read quickly (little conversion)
InputStream instr = new FileInputStream( "mydata" );
DataInputStream data = new DataInputStream( instr );
try {
int n = data.readInt( ); // 4 bytes
double x = data.readDouble( ); // 8 bytes
char c = data.readChar( ); // 2 bytes
} catch ( IOException e ) { ... }
788 
Throws EOFException if end of input encountered
while reading.
InputStream fin = new FileInputStream( "mydata" );
DataInputStream data = new DataInputStream( fin );
double sum = 0;
while( true ) {
try {
double x = data.readDouble( ); // 8 bytes
sum += x;
} catch ( IOException e ) { ... }
catch ( EOFException e ) { break; } // EOF
}
data.close( );

java.util.Scanner is newer than the other classes.
Scanner "wraps" an InputStream or a String and
provides parsing and data conversion.
// scanner wraps an InputStream
InputStream in = new FileInputStream(...);
Scanner scanner = new Scanner( in );
// scanner to parse a String
String s = "Peanuts 10.0 Baht";
Scanner scan = new Scanner( s );
."#
Can test for presence of data.
Convert next token into any primitive or get entire line as
String.
Scanner scanner = new Scanner("3 dogs .5");
if ( scanner.hasNextInt() )
n = scanner.nextInt();
if ( scanner.hasNext() )
word = scanner.next();
if ( scanner.hasNextDouble() )
x = scanner.nextDouble();
// read and discard rest of this line
scanner.nextLine();
@"#
Can change separator character.
Can search using regular expressions.
Scanner scanner = new Scanner("aa,bb,999");
scanner.useDelimiter(",");
String word = scanner.next(); // = "aa"
String w = scanner.findInLine("\\d\\d\\d");
// w is "999"
\d is a regular expression for a digit 0-9

Three layers, just like Input hierarchy
OutputStream: outputs bytes (low level)
Writer: outputs characters (convert to bytes)
BufferedWriter: outputs strings and lines. buffers data
Formatter: utility for creating formatted output. Can be
used as a pre-filter for an output stream or output to
any Appendable object.

OutputStream writes bytes to some output sink.
No interpretation of character sets.
Works OK for text in system's default character set.


&'''(
#A$
'#)$*(
#$
'#)$+,$*(
B$5
'B)*(

')*(

$-

Writer converts UNICODE characters to bytes.
Interprets chars according to character set encoding.
Can handle any language (if you know the charset).



&
#)
'/012340*(
#
'#)*(
#
+,&'''(
'#)*(

$-



Java has several classes derived from OutputStream
and Writer. Each class handles a particular output sink.
OutputStream Writer
 
 
 .
@ @
"
Writing Binary Data
 #)*
#)*
>C 7
%"7:
The Java input and output methods will throw an IOException if
there is an error in any input/output operation such read(),
write(), or print(). Your program must deal with this exception in
one of two ways:
1. Throw the exception..
public void myMethod throws IOException( ) {
// read and process the input
}
2. Catch the exception and take some action. This is illustrated on
the next slide.
"7:
BufferedReader myfile;
try {
myfile = new BufferedReader(
new FileReader( filename ) );
} catch (IOException e) {
System.out.println(
"Couldn't open file" + filename);
return;
}
// read a line from file
try {
String s = myfile.readLine( );
// do something with string
} catch (IOException e) {
System.out.println("Exception "+e
+ " while reading file.");
}
>"
The FileInputStream, FileOutputStream, FileReader, and FileWriter
classes operate on File objects.
Create a File object by specifying the filename (and optional path):
9A&#)0':0*(00
9D&#)0':0*(
9E&#)0FFFF':0*("
94&#)00/0':0*("
&#)00*( 9
These commands do not create a file in the computer's
file system. They only create a File object in Java.
"
The File class has methods to:
test file existence and permissions
create a file, delete a file
get file properties, such as path
9&#)0':0*(9$-
)9':)*!!9'.)**G
9&#)9*(
)<9':)**9'C#)*(9<
)9')** G#
&#)9*(
1
9&#)0"':0*(9$-
)9')**=
H9H
""&9'")*(
"&9'19)*(
?
)9' )**=
HH
9+,&9')*(
?
File objects can tell you their size, location (path),
modification time, etc. See the Java API for File.
7:
File infile = new File("/temp/old.txt");
File outfile = new File("/temp/new.txt");
if ( outfile.exists( ) ) outfile.delete( );
outfile.createNewFile( );
FileReader fin = new FileReader( infile );
FileWriter fout = new FileWriter( outfile );
// reading char at a time is very inefficient
int c;
while ( (c = fin.read()) >= 0 ) fout.write(c);
fin.close();
fout.flush();
fout.close();
opy a file. Realistically, you should test file existence
and permissions, catch IOException, etc.
@
PipedOutputStream pout = new PipedOutputStream();
PipedInputtStream pin = new PipedInputStream( pout );
PrintStream out = new PrintStream( pout );
BufferedInputStream in = new BufferedInputStream( pin );
out.println("data into the pipe"); // write to the pipe
String s = in.readLine( ); // read from the pipe
Reading and writing pipes: one method writes data into the pipe,
another method reads data from the pipe.
Very useful for multi-threaded applications.
PipedOutputStream pout =
new PipedOutputStream();
PipedInputStream pin =
new PipedInputStream(pout);
I
InputStream and Readers read the input from start to
end.
OutputStream and Writers write the output from start to
end.
This is called Sequential Access.
JI
Read/write everything starting from the beginning.
Sequential:
Cannot "back up" and reread or rewrite something.
Cannot "jump" to arbitrary location in stream.
InputStream and OutputStream use sequential I/O.
InputStream has a skip(n), but it is still sequential.
eS q u
i
a l
I O
. . .
e n t
int a = instream.read( ); // read a = 'S'
byte [ ] b = new byte[10];
int count = instream.read( b ); // read next 10 bytes
.I
Can move to any location using seek( ) method.
Can move forward and backward.
Only makes sense for files.
aR n d
A
c c
I O
. . .
o m
File file = new File( "c:/data/myfile.txt" );
RandomAccessFile rand =
new RandomAccessFile(file, "r");
rand.seek( 9L ); // goto byte 9
int b = rand.read( );
.I
Random Access I/O means you can move around in
the file, reading/writing at any place you want.
For output, you can even write beyond the end of file.
Use seek( ) to move current position.
RandomAccessFile ra = new RandomAccessFile("name", "rw");
ra.seek( 100000L ); // go to byte #100000
byte [ ] b = new byte[1000];
// all "read" methods are binary, like DataInputStream
ra.readFully( b ); // read 1000 bytes
ra.seek( 200000L ); // go to byte #200000
ra.write( b );
1
)*
K.""
K-''$6
%"7#7:
K-''$6:
