CS2514
Introduction to Java
Dr Derek Bridge
School of Computer Science & Information Technology
University College Cork
Problems at run-time
- Run-time errors arise when your program compiles but, at run-time,
it tries to carry out an illegal operation
- e.g. null pointer exception, index out of bounds exception,
division by zero exception
- you deal with these by testing and debugging your program
- But other run-time problems cannot be solved in this way:
- Suppose your program is communicating with an external
resource (user, file, database, network connection)
- What can go wrong?
- You must write code that detects these problems and
responds gracefully to them
Reading & writing bytes
- The
File
class:
- objects that represent files (or directories) on the host file
system
- these are objects in memory; they may or may not correspond
to actual files or directories
File
's interface: exists
,
isDirectory
, isFile
,
canRead
, canWrite
FileInputStream
for reading bytes: constrructor opens
the file; read
reads a byte but returns -1 if reading
beyond end of file;
program termination closes the file (but can use close
);
opening/reading/closing may throw IOException
FileOutputStream
for writing bytes: constructor opens
the file (generally creating it if it does not exist); write
writes a byte; program termination closes the file (but can use
close
); opening/writing/closing can throw
IOException
)
In a word, what does this program do?
import java.io.*;
class Mystery {
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream(new File("file1.txt"));
FileOutputStream fos = new FileOutputStream(new File("file2.txt"));
while (true) {
int nextByte = fis.read();
if (nextByte == -1) {
break;
}
fos.write(nextByte);
}
fis.close();
fos.close();
} catch (IOException e) {
System.out.println("Sorry something has gone wrong: " + e.getMessage());
}
}
}
Chaining streams together
FileOutputStream
writes bytes – but we don't
want to write bytes!
- Maybe want to write binary data – in the same
format that Java uses internally
- Or maybe we want to write data as text – so
that it is human readable
- Or maybe we want to write whole objects –
very convenient!
- To achieve this, we chain different streams together
- E.g. to write binary data, chain together a
DataOutputStream
and a FileOutputStream
- Include a
BufferedOutputStream
'in the middle'
for efficiency
Serialization: reading/writing objects
LibraryBook
import java.io.Serializable;
class LibraryBook implements Serializable {
private String author;
private String title;
private int numCopiesPossessed;
private int numCopiesOnLoan;
public LibraryBook(String author, String title) {
this.author = author;
this.title = title;
}
public LibraryBook(String author, String title, int numCopies) {
this(author, title);
this.numCopiesPossessed = numCopies;
}
public int getNumCopiesPossessed() {
return numCopiesPossessed;
}
public int getNumCopiesOnLoan() {
return numCopiesOnLoan;
}
public int getNumCopiesOnShelves() {
return numCopiesPossessed - numCopiesOnLoan;
}
public void acquire() {
numCopiesPossessed = numCopiesPossessed + 1;
}
public void acquire(int numNewCopies) {
numCopiesPossessed = numCopiesPossessed + numNewCopies;
}
public void takeOut() {
numCopiesOnLoan = numCopiesOnLoan + 1;
}
public void bringBack() {
numCopiesOnLoan = numCopiesOnLoan - 1;
}
public String toString() {
return author + ": " + title + ", " + numCopiesPossessed + " copies";
}
}
Writing and reading an object
- For example, if
b
is a variable that references
a LibraryBook
object, we can write the object to
a file in a single operation:
File file = new File("book.ser");
ObjectOutputStream oos =
new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
oos.writeObject(b);
- Similarly, we can read an object in a single operation:
ObjectInputStream ois =
new ObjectInputStream(new BufferedInputStream(new FileInputStream(file)));
LibraryBook b = (LibraryBook) ois.readObject();
- Reading requires casting – discussed in a later lecture
- (Advanced: lots more details, e.g.
static/transient
variables)
Library
import java.io.Serializable;
class Library implements Serializable {
private LibraryBook[] books;
public Library() {
books = new LibraryBook[0];
}
public void addBook(LibraryBook book) {
LibraryBook[] temp = new LibraryBook[books.length + 1];
for (int i = 0; i < books.length; i = i + 1) {
temp[i] = books[i];
}
temp[books.length] = book;
books = temp;
}
public String toString() {
String str = "";
for (int i = 0; i < books.length; i = i + 1) {
str = str + books[i] + "\n";
}
return str;
}
}
So what happens here?
import java.util.Scanner;
import java.io.*;
class LibraryTester {
public static void main(String[] args) {
try {
Library lib;
File file = new File("library.ser");
if (file.exists()) {
ObjectInputStream ois =
new ObjectInputStream(
new BufferedInputStream(new FileInputStream(file)));
lib = (Library) ois.readObject();
ois.close();
} else {
lib = new Library();
}
System.out.println(lib);
Scanner sc = new Scanner(System.in);
System.out.print("Author: ");
String author = sc.nextLine();
System.out.print("Title: ");
String title = sc.nextLine();
System.out.print("Copies acquired: ");
int numNewCopies = sc.nextInt();
LibraryBook b = new LibraryBook(author, title, numNewCopies);
lib.addBook(b);
ObjectOutputStream oos =
new ObjectOutputStream(
new BufferedOutputStream(new FileOutputStream(file)));
oos.writeObject(lib);
oos.close();
} catch (IOException e) {
System.out.println("Sorry - unable to read or write to file");
} catch (ClassNotFoundException e) {
System.out.println("Sorry - file does not contain a library");
}
}
}