Java IO and Files
Programming-3
Lecture 04
Dr. Mohammad Ahmad
Overview
• Java I/O
– The java.io package
– Streams
• Files
– Working with Files
Java I/O – The Basics
• Java I/O is based around the concept of a stream
– Ordered sequence of information (bytes) coming from a
source, or going to a ‘sink’
– Simplest stream reads/writes only a single byte, or an
array of bytes at a time
• Designed to be platform-independent
• The stream concept is very generic
– Can be applied to many different types of I/O
– Files, Network, Memory, Processes, etc
Streams
• Stream: an object that either delivers data to its destination (screen,
file, etc.) or that takes data from a source (keyboard, file, etc.)
– it acts as a buffer between the data source and destination
• Input stream: a stream that provides input to a program
– System.in is an input stream
• Output stream: a stream that accepts output from a program
– System.out is an output stream
• A stream connects a program to an I/O object
– System.out connects a program to the screen
– System.in connects a program to the keyboard
Binary Versus Text Files
• All data and programs are ultimately just zeros and ones
– each digit can have one of two values, hence binary
– bit is one binary digit
– byte is a group of eight bits
• Text files: the bits represent printable characters
– one byte per character for ASCII, the most common code
– for example, Java source files are text files
– so is any file created with a "text editor"
• Binary files: the bits represent other types of encoded information, such as
executable instructions or numeric data
– these files are easily read by the computer but not humans
– they are not "printable" files
• actually, you can print them, but they will be unintelligible
• "printable" means "easily readable by humans when printed"
Java I/O – The Basics
• The java.io package contains all of the I/O
classes.
– Many classes specialised for particular kinds of stream
operations, e.g. file I/O
• Reading/writing single bytes is quite limited
– So, it includes classes which provide extra functionality
– e.g. buffering, reading numbers and Strings (not bytes),
etc.
• Results in large inheritance hierarchy, with
separate trees for input and output stream classes
Java I/O -- InputStream
Java I/O – InputStreams
Java I/O – Using InputStreams
• Basic pattern for I/O programming is as
follows:
Open a stream
While there’s data to read
Process the data
Close the stream
Java I/O – Using InputStreams
• I/O in Java:
InputStream in = new FileInputStream(“c:\\temp\\
myfile.txt”);
int b = in.read();
//EOF is signalled by read() returning -1
while (b != -1)
{
//do something…
b = in.read();
}
in.close();
Java I/O – Using InputStreams
• But using buffering is more efficient, therefore we
always nest our streams…
InputStream inner = new FileInputStream(“c:\\temp\\
myfile.txt”);
InputStream in = new BufferedInputStream(inner);
int b = in.read();
//EOF is signalled by read() returning -1
while (b != -1)
{
//do something…
b = in.read();
}
in.close();
Java I/O – Using InputStreams
• We’ve omitted exception handling in the
previous examples
• Almost all methods on the I/O classes
(including constructors) can throw an
IOException or a subclass.
• Always wrap I/O code in try…catch blocks
to handle errors.
Java I/O – Using InputStreams
InputStream in = null;
try
{
InputStream inner = new FileInputStream(“c:\\temp\\
myfile.txt”);
in = new BufferedInputStream(inner);
//process file
} catch (IOException e)
{
e.printStackTrace();
}
finally
{
try { in.close(); } catch (Exception e) {}
}
Java I/O – OutputStream
Java I/O – OutputStreams
Java I/O – Using InputStreams
• Basic pattern for output is as follows:
Open a stream
While there’s data to write
Write the data
Close the stream
Java I/O – Using
OutputStreams
• Output in Java:
OutputStream out = new FileOutputStream(“c:\\temp\\
myfile.txt”);
while (…)
{
out.write(…);
}
out.close();
Java I/O – Using
OutputStreams
OutputStream out = null;
try
{
OutputStream inner = new FileOutputStream(“c:\\temp\\
myfile.txt”);
out = new BufferedOutputStream(inner);
//write data to the file
} catch (IOException e)
{
e.printStackTrace();
}
finally
{
try { out.close(); } catch (Exception e) {}
}
Unicode
• Each character in the ASCII character set fits into a
single byte
– …but that’s not enough for chinese, and other complex
alphabets
– Need more than a single byte
– A Java character (char) is 2 bytes
• Java handles text using Unicode
– International standard character set, containing characters
for almost all known languages
– And a few imaginary ones! (Klingon, Elvish…)
• Inside the JVM all text is held as Unicode
Java Text I/O
• Because byte != character for all languages, you
have to turn bytes into chars using a
Input/OutputStream
• Java provides Readers and Writers to save you
this work.
• These classes deal with streams of characters
– Read/write single character or array of characters
– Again there are classes specialised for particular
purposes
Java I/O – Reader
Java I/O – Readers
Using Readers
Reader in = null;
try
{
Reader inner = new FileReader(“c:\\temp\\myfile.txt”);
in = new BufferedReader(inner);
//process file
} catch (IOException e)
{
e.printStackTrace();
}
finally
{
try { in.close(); } catch (Exception e) {}
}
Java I/O – Writer
Java I/O – Writers
Using Writers
Writer out = null;
try
{
Writer inner = new FileWriter(“c:\\temp\\myfile.txt”);
out = new BufferedWriter(inner);
//write data to the file
} catch (IOException e)
{
e.printStackTrace();
}
finally
{
try { out.close(); } catch (Exception e) {}
}
Text File I/O
• Important classes for text file output (to the file)
– PrintWriter
– FileOutputStream [or FileWriter]
• Important classes for text file input (from the file):
– BufferedReader
– FileReader
• FileOutputStream and FileReader take file names as arguments.
• PrintWriter and BufferedReader provide useful methods for
easier writing and reading.
• Usually need a combination of two classes
• To use these classes your program needs a line like the following:
import java.io.*;
Text File Output
• To open a text file for output: connect a text file to a stream for writing
PrintWriter outputStream =
new PrintWriter(new FileOutputStream("out.txt"));
• Similar to the long way:
FileOutputStream s = new FileOutputStream("out.txt");
PrintWriter outputStream = new PrintWriter(s);
• Goal: create a PrintWriter object
– which uses FileOutputStream to open a text file
• FileOutputStream “connects” PrintWriter to a text file.
Output File Streams
PrintWriter FileOutputStream
Memory Disk
smileyOutStream smiley.txt
PrintWriter smileyOutStream = new PrintWriter( new FileOutputStream(“smiley.txt”) );
Methods for PrintWriter
• Similar to methods for System.out
• println
outputStream.println(count + " " + line);
• print
• format
• flush: write buffered output to disk
• close: close the PrintWriter stream (and file)
Bridging the Gap
• Sometimes you need to bridge across the two
hierachies
– Use InputStreamReader or OutputStreamWriter
• InputStreamReader
– Reads bytes from an InputStream, and turns them into
characters using a character encoding
• OutputStreamWriter
– Turns characters sent to the Writer into bytes written by
the OutputStream, again using a character encoding.
The File Object
• Java provides access to the file system through the
java.io.File object
– Represents files and directories
• Has methods for working with files and directories
– Making directories, listing directory contents
– renaming and deleting, checking permissions, etc
• Check whether the File corresponds to a directory or a
file with isDirectory()
• Well-featured, and intuitive
– Take a look through the javadocs
• Quick example…
File Class [java.io]
• Acts like a wrapper class for file names
• A file name like "numbers.txt" has only String properties
• File has some very useful methods
– exists: tests if a file already exists
– canRead: tests if the OS will let you read a file
– canWrite: tests if the OS will let you write to a file
– delete: deletes the file, returns true if successful
– length: returns the number of bytes in the file
– getName: returns file name, excluding the preceding path
– getPath: returns the path name—the full name
File numFile = new File(“numbers.txt”);
if (numFile.exists())
System.out.println(numfile.length());
Alternative with Scanner
•Use Scanner with File:
Scanner inFile =
new Scanner(new File(“in.txt”));
•Similar to Scanner with System.in:
Scanner keyboard =
new Scanner(System.in);
Reading in int’s
Scanner inFile = new Scanner(new File(“in.txt"));
int number;
while (inFile.hasInt())
{
number = inFile.nextInt();
// …
}
Reading in lines of characters
Scanner inFile = new Scanner(new File(“in.txt"));
String line;
while (inFile.hasNextLine())
{
line = inFile.nextLine();
// …
}
Multiple types on one line
// Name, id, balance
Scanner inFile = new Scanner(new File(“in.txt"));
while (inFile.hasNext())
{
name = inFile.next();
id = inFile.nextInt();
balance = inFile.nextFloat();
// … new Account(name, id, balance);
}
--------------------
String line;
while (inFile.hasNextLine())
{
line = inFile.nextLine();
Scanner parseLine = new Scanner(line) // Scanner again!
name = parseLine.next();
id = parseLine.nextInt();
balance = parseLine.nextFloat();
// … new Account(name, id, balance);
}
Multiple types on one line
// Name, id, balance
Scanner inFile = new Scanner(new File(“in.txt"));
String line;
while (inFile.hasNextLine())
{
line = inFile.nextLine();
Account account = new Account(line);
}
--------------------
public Account(String line) // constructor
{
Scanner accountLine = new Scanner(line);
_name = accountLine.next();
_id = accountLine.nextInt();
_balance = accountLine.nextFloat();
}
BufferedReader vs Scanner
(parsing primitive types)
• Scanner
– nextInt(), nextFloat(), … for
parsing types
• BufferedReader
– read(), readLine(), … none for
parsing types
BufferedReader vs Scanner
(Checking End of File/Stream (EOF))
• BufferedReader
– readLine() returns null
– read() returns -1
• Scanner
– nextLine() throws exception
– needs hasNextLine() to check first
– nextInt(), hasNextInt(), …
BufferedReader inFile = …
line = inFile.readline();
while (line != null)
{
// …
line = inFile.readline();
}
-------------------
Scanner inFile = …
while (inFile.hasNextLine())
{
line = infile.nextLine();
// …
}
BufferedReader inFile = …
line = inFile.readline();
while (line != null)
{
// …
line = inFile.readline();
}
-------------------
BufferedReader inFile = …
while ((line = inFile.readline()) != null)
{
// …
}
My suggestion
• Use Scanner with File
– new Scanner(new File(“in.txt”))
• Use hasNext…() to check for EOF
– while (inFile.hasNext…())
• Use next…() to read
– inFile.next…()
• Simpler and you are familiar with
methods for Scanner
My suggestion cont…
• File input
– Scanner inFile =
new Scanner(new File(“in.txt”));
• File output
– PrintWriter outFile =
new PrintWriter(new File(“out.txt”));
– outFile.print(), println(),
format(), flush(), close(), …