82
Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 1 C hapter19 How to w ork w ith textand binary files

Murach’s Beg. Java 2, JDK 5, C19© 2005, Mike Murach & Associates, Inc.Slide 1

  • View
    220

  • Download
    0

Embed Size (px)

Citation preview

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 1

Chapter 19

How to work with text and binary files

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 2

Objectives

Applied

Write code that uses the File class to get information about a file or directory.

Write code that reads and writes data to a text file using buffered readers and writers.

Use the string handling features that were presented in chapter 12 to process text read from a delimited text file.

Write code that reads and writes data to a binary file using primitive data types and fixed-length strings.

Write code that reads and writes random-access files.

Given the specifications for an application that stores its data in a text or binary file, implement the program using the file handling features presented in this chapter.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 3

Objectives (continued)

Knowledge

Explain the differences between a text file and a binary file.

Explain the concept of layering and how it is used to create filtered streams that can read or write files.

Explain how a buffer for an output stream works and how it improves the performance of an I/O operation.

Name and describe the three common types of I/O exceptions.

Describe the functions provided by the BufferedWriter, PrintWriter, and FileWriter classes when reading data from a text file.

Describe the functions provided by the BufferedReader and FileReader classes when writing to text files.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 4

Objectives (continued) Describe the functions provided by the DataOutputStream

BufferedOutputStream, and FileOutputStream classes when writing data to a binary file.

Describe the functions provided by the DataInputStream, BufferedInputStream, and FileInputStream classes when reading data from a binary file.

List two ways that strings can be stored in a binary file and describe the difference between the techniques.

Explain the differences in the use of random-access and sequential-access files.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 5

The File class java.io.File

One constructor of the File class

Constructor Description

File(StringPath) Creates a File object that refers to the specified path name.

Methods that check a File object

Method Returns a true value if…

exists() The path name exists.

canRead() The path name exists and a program can read from it.

canWrite() The path name exists and a program can write to it.

isDirectory() The path name exists and refers to a directory.

isFile() The path name exists and refers to a file.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 6

Methods that get information about a File object

Method Description

getName() Returns the name of the file or directory as a String object.

getPath() Returns the path name as represented in the constructor as a String object.

getAbsolutePath() Returns the absolute path name as a String object.

length() Returns the length of the file in bytes as a long type.

lastModified() Returns a long value representing the time that the file was last modified as the number of milliseconds since January 1, 1970.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 7

Methods that get information about a File object (continued)

Method Description

listRoots() A static method that returns an array of File objects representing the drives available to the current system.

listFiles() If the object refers to a directory, this method returns an array of File objects for the files and subdirectories of this directory.

list() If the object refers to a directory, this method returns an array of String objects for the files and subdirectories of this directory.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 8

Methods that work with File objects

Method Description

setReadOnly() Makes the object read-only. If successful, this method returns a true value.

createNewFile() Creates a new file for the file represented by the File object if one doesn’t already exist. Returns a true value if the file is created. This method throws IOException.

mkdirs() Creates a new directory for the directory represented by this File object including any necessary but non-existent parent directories. Returns a true value if the directory is created.

delete() Deletes the file or directory represented by the File object. If successful, this method returns a true value. A directory can only be deleted if it’s empty.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 9

Coding the elements in a file path name When coding directory names, you can use a front slash to

separate directories.

To identify the name and location of a file, you can use:

an absolute path name to specify the entire path for a file, or

a relative path name to specify the path of the file relative to another directory

To create a File object that represents a file on a remote computer, you can use the Universal Naming Convention (UNC). To do that, code two slashes (//) followed by the host name and the share name.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 10

Code that creates a directory if it doesn’t already exist

String dirName = "c:/java 1.5/files/"; File dir = new File(dirName); if (!dir.exists()) dir.mkdirs();

Code that creates a file if it doesn’t already exist String fileName = "products.txt"; File productsFile = new File(dirName + fileName); if (!productsFile.exists()) productsFile.createNewFile();

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 11

Code that displays information about a file System.out.println( "File name: " + productsFile.getName()); System.out.println( "Absolute path: " + productsFile.getAbsolutePath()); System.out.println( "Is writable: " + productsFile.canWrite());

Resulting output File name: products.txt Absolute path: c:\java 1.5\files\products.txt Is writable: true

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 12

Code that displays information about a directory if (dir.exists() && dir.isDirectory()) { System.out.println("Directory: " + dir.getAbsolutePath()); System.out.println("Files: "); for (String filename : dir.list()) System.out.println(" " + filename); }

Resulting output Directory: c:\java 1.5\files Files: customers.txt products.txt

Code that specifies a directory and file on a remote server

String dirName = "//server/c/editorial/customers.txt";

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 13

A text file that’s opened by a text editor

A binary file that’s opened by a text editor

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 14

Two types of files

File Description

Text A file that contains characters. The fields and records in this type of file are often delimited by special characters like tab and new line characters.

Binary A file that may contain characters as well as other non-character data types that can’t be read by a text editor.

Two types of streams

Stream Description

Character Used to transfer text data to or from an I/O device.

Binary Used to transfer binary data to or from an I/O device.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 15

How files and streams work An input file is a file that is read by a program.

An output file is a file that is written by a program.

Input and output operations are often referred to as I/O operations or file I/O.

A stream is the flow of data from one location to another.

To write data to a file from internal storage, you use an output stream.

To read from a file into internal storage, you use an input stream.

To read and write text files, you use character streams.

To read and write binary files, you use binary streams.

Streams are not only used with disk devices, but also with input devices like keyboards and network connections and output devices like PC monitors and network connections.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 16

Handling file I/O The java.io package contains dozens of classes that can be used to

create different types of streams that have different functionality.

The java.nio package contains even more classes for working with I/O.

To get the functionality you need for a stream, you often need to combine, or layer, two or more streams.

To make disk processing more efficient, you can use a buffered stream that adds a block of internal memory called a buffer to the stream.

When working with buffers, you often need to flush the buffer. This sends all data in the buffer to the I/O device. One way to do that is to close the I/O stream.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 17

A file I/O example

Import all classes in the java.io package import java.io.*;

Create a File object File productsFile = new File("products.txt");

Write data to the file Step 1: Open a buffered output stream PrintWriter out = new PrintWriter( new BufferedWriter( new FileWriter(productsFile)));

Step 2: Write data to the stream out.println("java\tMurach's Beginning Java 2\t49.50");

Step 3: Close the stream and flush all data to the file out.close();

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 18

A file I/O example (continued)

Read data from the file Step 1: Open a buffered input stream BufferedReader in = new BufferedReader( new FileReader(productsFile));

Step 2: Read data from the stream and print it to the console String line = in.readLine(); System.out.println(line);

Step 3: Close the stream out.close();

Resulting output java Murach's Beginning Java 2 49.50

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 19

A subset of the IOException hierarchy IOException EOFException FileNotFoundException

Common I/O exceptions

Exception Description

IOException Thrown when an error occurs in I/O processing.

EOFException Thrown when a program attempts to read beyond the end of a file.

FileNotFoundException Thrown when a program attempts to open a file that doesn’t exist.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 20

Code that handles I/O exceptions BufferedReader in = null; try { if (productsFile.exists()) // prevent the FileNotFoundException { in = new BufferedReader( new FileReader(productsFile)); String line = in.readLine(); while(line != null) { System.out.println(line); line = in.readLine(); } } else System.out.println(productsFile.getPath() + " doesn't exist"); }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 21

Code that handles I/O exceptions (continued) catch(IOException ioe) // catch any other IOExceptions { System.out.println(ioe); } finally // close the stream even if an exception was thrown { this.close(in); // call the close method }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 22

A method that closes a stream private void close(Closeable stream) { try { if (stream != null) // prevent a NullPointerException stream.close(); } catch(IOException ioe) { System.out.println("Unable to close stream: " + ioe); } }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 23

A subset of the Writer hierarchy Writer <<abstract>> BufferedWriter PrintWriter OutputStreamWriter FileWriter

Classes used to connect a character output stream to a file PrintWriter contains the methods for writing data to a text stream

BufferedWriter creates a buffer for the stream

FileWriter connects the stream to a file

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 24

Constructors of these classes

Constructor Throws

PrintWriter(Writer[, booleanFlush]) None

BufferedWriter(Writer) None

FileWriter(File[, booleanAppend]) IOException

FileWriter(StringFileName[, booleanAppend]) IOException

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 25

How to connect a character output stream to a file without a buffer (not recommended)

FileWriter fileWriter = new FileWriter("products.txt"); PrintWriter out = new PrintWriter(fileWriter);

A more concise way to code the same thing PrintWriter out = new PrintWriter(new FileWriter("products.txt"));

How to connect to a file with a buffer PrintWriter out = new PrintWriter( new BufferedWriter( new FileWriter(productsFile)));

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 26

How to connect for an append operation PrintWriter out = new PrintWriter( new BufferedWriter( new FileWriter(productsFile, true)));

How to connect with the autoflush feature turned on

PrintWriter out = new PrintWriter( new BufferedWriter( new FileWriter(productsFile)), true);

Notes By default, if the output file already exists, it’s overwritten. If

that’s not what you want, you can specify true for the second argument of the FileWriter constructor to append data to the file.

If you specify true for the second argument of the PrintWriter constructor, the autoflush feature flushes the buffer each time the println method is called.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 27

How to write to a text file To write a character representation of a data type to an output

stream, you use the print and println methods of the PrintWriter class.

If you supply an object as an argument, these methods will call the toString method of the object.

To create a delimited text file, you delimit the records in the file with one delimiter, such as a new line character, and you delimit the fields of each record with another delimiter, such as a tab character.

To prevent data from being lost, you should always close the stream when you’re done using it. Then, the program will flush all data to the file before it closes the stream.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 28

Common methods of the PrintWriter class

Method Throws Description

print(argument) None Writes the character representation of the argument type to the file.

println(argument) None Writes the character representation of the argument type to the file followed by the new line character. If the autoflush feature is turned on, this also flushes the buffer.

flush() IOException Flushes any data that’s in the buffer to the file.

close() IOException Flushes any data that’s in the buffer to the file and closes the stream.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 29

Code that appends a string and an object to a text file

// open an output stream for appending to the text file PrintWriter out = new PrintWriter( new BufferedWriter( new FileWriter("log.txt", true))); // write a string and an object to the file out.print("This application was run on "); Date today = new Date(); out.println(today); // flush data to the file and close the output stream out.close();

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 30

Code that writes a Product object to a delimited text file

// open an output stream for overwriting a text file PrintWriter out = new PrintWriter( new BufferedWriter( new FileWriter(productsFile))); // write the Product object to the file out.print(product.getCode() + "\t"); out.print(product.getDescription() + "\t"); out.println(product.getPrice()); // flush data to the file and close the output stream out.close();

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 31

A subset of the Reader hierarchy Reader <<abstract>> BufferedReader InputStreamReader FileReader

Notes All classes in the java.io package that end with Reader are

members of the Reader hierarchy.

Although you can read files with the FileReader class alone, the BufferedReader class improves efficiency and provides better methods for reading character input streams.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 32

Classes used to connect to a file with a buffer BufferedReader contains methods for reading data from the stream

FileReader connects the stream to a file

Constructors of these classes

Constructor Throws

BufferedReader(Reader) None

FileReader(File) FileNotFoundException

FileReader(StringFileName) FileNotFoundException

How to connect a character input stream to a file BufferedReader in = new BufferedReader( new FileReader(productsFile));

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 33

Common methods of the BufferedReader class

Method Throws Description

readLine() IOException Reads a line of text and returns it as a string.

read() IOException Reads a single character and returns it as an int that represents the ASCII code for the character. When this method attempts to read past the end of the file, it returns an int value of -1.

skip(longValue) IOException Attempts to skip the specified number of characters, and returns an int value for the actual number of characters skipped.

close() IOException Closes the input stream and flushes the buffer.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 34

Code that reads the records in a text file // read the records of the file String line = in.readLine(); while(line != null) { System.out.println(line); line = in.readLine(); } // close the input stream in.close();

Sample output This application was run on Tue Oct 19 09:21:42 PDT 2004 This application was run on Wed Oct 20 10:14:12 PDT 2004

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 35

Code that reads a Product object from a delimited text file

// read the next line of the file String line = in.readLine(); // parse the line into its columns String[] columns = line.split("\t"); String code = columns[0]; String description = columns[1]; String price = columns[2]; // create a Product object from the data in the columns Product p = new Product(code, description, Double.parseDouble(price)); // print the Product object System.out.println(p); // close the input stream in.close();

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 36

Sample output from the code that reads a Product object from a delimited text file Code: java Description: Murach's Beginning Java Price: $49.50

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 37

The ProductDAO interface public interface ProductDAO extends ProductReader, ProductWriter, ProductConstants {}

The ProductReader interface import java.util.ArrayList; public interface ProductReader { Product getProduct(String code); ArrayList<Product> getProducts(); }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 38

The ProductWriter interface public interface ProductWriter { boolean addProduct(Product p); boolean updateProduct(Product p); boolean deleteProduct(Product p); }

The ProductConstants interface public interface ProductConstants { int CODE_SIZE = 4; int DESCRIPTION_SIZE = 40; }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 39

A class that works with a text file import java.io.*; import java.util.*; public class ProductTextFile implements ProductDAO { private File productsFile = null; private final String FIELD_SEP = "\t"; public ProductTextFile() { productsFile = new File("products.txt"); } private void checkFile() throws IOException { // if the file doesn't exist, create it if (!productsFile.exists()) productsFile.createNewFile(); }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 40

A class that works with a text file (continued) private boolean saveProducts(ArrayList<Product> products) { PrintWriter out = null; try { this.checkFile(); // open output stream for overwriting out = new PrintWriter( new BufferedWriter( new FileWriter(productsFile))); // write all products in the array list // to the file for (Product p : products) { out.print(p.getCode() + FIELD_SEP); out.print(p.getDescription() + FIELD_SEP); out.println(p.getPrice()); } }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 41

A class that works with a text file (continued) catch(IOException ioe) { ioe.printStackTrace(); return false; } finally { this.close(out); } return true; } private void close(Closeable stream) { try { if (stream != null) stream.close(); } catch(IOException ioe) { ioe.printStackTrace(); } }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 42

A class that works with a text file (continued) public ArrayList<Product> getProducts() { BufferedReader in = null; try { this.checkFile(); in = new BufferedReader( new FileReader(productsFile)); ArrayList<Product> products = new ArrayList<Product>(); // read all products stored in the file // into the array list String line = in.readLine(); while(line != null) { String[] columns = line.split(FIELD_SEP); String code = columns[0]; String description = columns[1]; String price = columns[2];

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 43

A class that works with a text file (continued) Product p = new Product( code, description, Double.parseDouble(price)); products.add(p); line = in.readLine(); } return products; } catch(IOException ioe) { ioe.printStackTrace(); return null; } finally { this.close(in); } }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 44

A class that works with a text file (continued) public Product getProduct(String code) { ArrayList<Product> products = this.getProducts(); for (Product p : products) { if (p.getCode().equals(code)) return p; } return null; } public boolean addProduct(Product p) { ArrayList<Product> products = this.getProducts(); products.add(p); return this.saveProducts(products); } public boolean deleteProduct(Product p) { ArrayList<Product> products = this.getProducts(); products.remove(p); return this.saveProducts(products); }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 45

A class that works with a text file (continued) public boolean updateProduct(Product newProduct) { ArrayList<Product> products = this.getProducts(); // get the old product and remove it Product oldProduct = this.getProduct(newProduct.getCode()); int i = products.indexOf(oldProduct); products.remove(i); // add the updated product products.add(i, newProduct); return this.saveProducts(products); } }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 46

A subset of the OutputStream hierarchy OutputStream <<abstract>> FileOutputStream FilterOutputStream BufferedOutputStream DataOutputStream <<implements DataOutput interface>>

Notes All classes in the java.io and java.util.zip packages that end with

OutputStream are members of the OutputStream hierarchy.

The FilterOutputStream class is a superclass of all classes that filter binary output streams.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 47

Classes used to connect a binary output stream to a file DataOutputStream writes data to the stream

BufferedOutputStream creates a buffer for the stream

FileOutputStream connects the stream to a file

Constructors of these classes

Constructor Throws DataOutputStream(OutputStream) None BufferedOutputStream(OutputStream) None FileOutputStream(File [, booleanAppend])

FileNotFoundException

FileOutputStream(StringFileName [, booleanAppend])

FileNotFoundException

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 48

A File object that refers to a binary file File productsFile = new File("products.dat");

How to connect a binary output stream to a file with a buffer DataOutputStream out = new DataOutputStream( new BufferedOutputStream( new FileOutputStream(productsFile)));

How to connect for an append operation DataOutputStream out = new DataOutputStream( new BufferedOutputStream( new FileOutputStream( productsFile, true)));

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 49

Common methods of the DataOutput interface

Method Throws Description

writeBoolean(boolean) IOException Writes a 1-byte boolean value to the output stream.

writeInt(int) IOException Writes a 4-byte int value.

writeDouble(double) IOException Writes an 8-byte double value.

writeChar(int) IOException Writes a 2-byte char value.

writeChars(String) IOException Writes a string using 2 bytes per character.

writeUTF(String) IOException Writes a 2-byte value for the number of bytes in the string followed by the UTF representation of the string.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 50

Methods of the DataOutputStream class

Method Throws Description

size() None Returns an int for the number of bytes written to this stream.

flush() IOException Flushes any data that’s in the buffer to the file.

close() IOException Flushes any data that’s in the buffer to the file and closes the stream.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 51

Code that writes data to a binary file // write a Product object to the file out.writeUTF(product.getCode()); out.writeUTF(product.getDescription()); out.writeDouble(product.getPrice()); // flush data to the file and close the output stream out.close();

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 52

A subset of the InputStream hierarchy InputStream {abstract} FileInputStream FilterInputStream BufferedInputStream DataInputStream {implements DataInput interface}

Notes All classes in the java.io and java.util.zip packages that end with

InputStream are members of the InputStream hierarchy.

The FilterInputStream class is a superclass of all classes that filter binary input streams.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 53

Classes used to connect a binary input stream to a file DataInputStream reads data from the stream

BufferedInputStream creates a buffer for the stream

FileInputStream connects the stream to the file

Constructors of these classes

Constructor Throws

DataInputStream(InputStream) None

BufferedInputStream(InputStream) None

FileInputStream(File) FileNotFoundException

FileInputStream(StringFileName) FileNotFoundException

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 54

How to connect a binary input stream to a file DataInputStream in = new DataInputStream( new BufferedInputStream( new FileInputStream(productsFile)));

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 55

Common methods of the DataInput interface

Method Throws Description

readBoolean() EOFException Reads 1 byte and returns a boolean value.

readInt() EOFException Reads 4 bytes and returns an int value.

readDouble() EOFException Reads 8 bytes and returns a double value.

readChar() EOFException Reads 2 bytes and returns a char value.

readUTF() EOFException Reads and returns the string encoded with UTF.

skipBytes(int) EOFException Tries to skip the specified number of bytes, and returns an int value for the actual number skipped.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 56

Common methods of the DataInputStream class

Method Throws Description

available() IOException Returns the number of bytes remaining in the file.

close() IOException Closes the stream.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 57

Code that reads a Product object from a binary file

// read product data from a file String code = in.readUTF(); String description = in.readUTF(); double price = in.readDouble(); // create the Product object from its data Product p = new Product(code, description, price); // close the input stream in.close();

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 58

Two ways to write a binary string // create a test string String testString = "This is a test string.\n"; // use the writeUTF method out.writeUTF(testString); int writeSize1 = out.size(); System.out.println( "writeUTF writes " + writeSize1 + " bytes."); // use the writeChars method out.writeChars(testString); int writeSize2 = out.size() - writeSize1; System.out.println( "writeChars writes " + writeSize2 + " bytes\n"); out.close();

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 59

Output of the code that writes a binary string writeUTF writes 25 bytes. writeChars writes 46 bytes.

The file opened in a text editor

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 60

Two ways to read a binary string // get total bytes int totalBytes = in.available(); // use the readUTF method String string1 = in.readUTF(); int readSize1 = totalBytes - in.available(); System.out.println( "readUTF reads " + readSize1 + " bytes."); // use the readChar method int readSize2 = 0; String string2 = ""; for (int i = 0; i < testString.length(); i++) { string2 += in.readChar(); readSize2 += 2; } System.out.println( "readChar reads " + readSize2 + " bytes.\n");

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 61

Output of the code that reads a binary string readUTF reads 25 bytes. readChar reads 46 bytes.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 62

How to connect to a random-access file You can use the classes in the OutputStream and InputStream

hierarchies to read and write files sequentially. These are called sequential-access files.

When you work with a sequential-access file, you read from the beginning of the file to the end, and you can add data only at the end of the file.

You can use the RandomAccessFile class to read and write files randomly. These are called random-access files.

When you work with a random-access file, you can move a pointer to any point in the file. Then, you can read and write data starting at that point.

The metadata for a file includes information about the file such as its size, the date it was last modified, and so on.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 63

Constructors of the RandomAccessFile class

Constructor Throws RandomAccessFile(File, stringMode)

FileNotFoundException

RandomAccessFile(StringFileName, stringMode)

FileNotFoundException

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 64

Access mode values

Value Description

r Open for reading only.

rw Open for reading and writing. If the file doesn’t already exist, an attempt will be made to create it.

rws Open for reading and writing and also require that every update to the file data or the metadata for the file be written synchronously to the underlying storage device.

rwd Open for reading and writing and also require that every update to the file data be written synchronously to the underlying storage device.

Note If you use one of the synchronized read-write modes, only one

user at a time can update the file.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 65

A File object that refers to a binary file File file = new File("products.dat");

How to create a read-write RandomAccessFile object

RandomAccessFile productsFile = new RandomAccessFile(file, "rw");

How to create a read-only RandomAccessFile object

RandomAccessFile productsFile = new RandomAccessFile(file, "r");

How to create a synchronized read-write object RandomAccessFile productsFile = new RandomAccessFile(file, "rws");

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 66

Two interfaces implemented by the RandomAccessFile class

DataOutput DataInput

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 67

Methods of the RandomAccessFile class used for input and output

Method Throws Description

seek(long) IOException Sets the pointer to the specified number of bytes from the beginning of the file. If set beyond the end of the file, the pointer will be moved to the end of the file.

length() IOException Returns a long for the number of bytes in the file.

setLength(long) IOException Sets the length of the file to the specified number of bytes.

close() IOException Closes the file.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 68

Code that writes data to a file RandomAccessFile productsFile = new RandomAccessFile(file, "rw"); // write 3 records with codes and prices to the file String[] codes = {"java", "jsps", "txtp"}; double[] prices = {49.5, 49.5, 20.0}; for (int i = 0; i < codes.length; i++) { productsFile.writeChars(codes[i]); productsFile.writeDouble(prices[i]); } productsFile.close();

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 69

Code that reads data from a file final int RECORD_LENGTH = 16; // 4 chars @ 2 bytes per char // + 1 double @ 8 bytes RandomAccessFile productsFile = new RandomAccessFile(file, "r"); // move the pointer to the third record int recordNumber = 3; productsFile.seek((recordNumber - 1) * RECORD_LENGTH); // read the third record String code = ""; for (int i = 0; i < 4; i++) code += productsFile.readChar(); double price = productsFile.readDouble(); productsFile.close();

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 70

How to read and write fixed-length strings When you write strings to a random-access file, you need to write

fixed-length strings.

That way, the length of the strings won’t vary from one record to another, and all of the record lengths in the file will be the same.

You can create a class that contains static methods to write and read fixed-length strings.

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 71

A class that writes and reads fixed-length strings import java.io.*; public class IOStringUtils { public static void writeFixedString( DataOutput out, int length, String s) throws IOException { for (int i = 0; i < length; i++) { if (i < s.length()) out.writeChar(s.charAt(i)); // write char else out.writeChar(0); // write unicode zero } }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 72

A class that writes and reads fixed-length strings (continued) public static String getFixedString( DataInput in, int length) throws IOException { StringBuilder sb = new StringBuilder(); for (int i = 0; i < length; i++) { char c = in.readChar(); // if char is not Unicode zero add to string if (c != 0) sb.append(c); } return sb.toString(); } }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 73

A class that works with a random-access file import java.io.*; import java.util.*; public class ProductRandomFile implements ProductDAO { private RandomAccessFile productsFile = null; private ArrayList<String> productCodes = null; private final int PRICE_SIZE = 8; // doubles are 8 bytes private final int RECORD_SIZE = CODE_SIZE * 2 + // from ProductConstants interface DESCRIPTION_SIZE * 2 + // from ProductConstants interface PRICE_SIZE; private final String DELETION_CODE = " "; public ProductRandomFile() { try { productsFile = new RandomAccessFile("products.ran", "rw"); productCodes = this.getCodes(); }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 74

A class that works with a random-access file (continued) catch(FileNotFoundException fnfe) { fnfe.printStackTrace(); } } public void finalize() { try { if (productsFile != null) productsFile.close(); } catch(IOException ioe) { ioe.printStackTrace(); } }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 75

A class that works with a random-access file (continued) //************************************************* // Private methods for reading products //************************************************* private int getRecordCount() throws IOException { int recordCount = (int) productsFile.length() / RECORD_SIZE; return recordCount; } private int getRecordNumber(String productCode) { for (int i = 0; i < productCodes.size(); i++) { String code = productCodes.get(i); if (productCode.equals(code)) return i; } return -1; // no record matches the product code }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 76

A class that works with a random-access file (continued) private Product getRecord(int recordNumber) throws IOException { if (recordNumber >= 0 && recordNumber < this.getRecordCount()) { productsFile.seek(recordNumber * RECORD_SIZE); String code = IOStringUtils.getFixedString( productsFile, CODE_SIZE); String description = IOStringUtils.getFixedString( productsFile, DESCRIPTION_SIZE); double price = productsFile.readDouble(); Product product = new Product(code, description, price); return product; } else return null; }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 77

A class that works with a random-access file (continued) private ArrayList<String> getCodes() { try { ArrayList<String> codes = new ArrayList<String>(); for (int i = 0; i < this.getRecordCount(); i++) { productsFile.seek(i * RECORD_SIZE); codes.add(IOStringUtils.getFixedString( productsFile, CODE_SIZE)); } return codes; } catch(IOException ioe) { ioe.printStackTrace(); return null; } }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 78

A class that works with a random-access file (continued) //********************************************************* // Public methods for reading products //********************************************************* public ArrayList<Product> getProducts() { ArrayList<Product> products = new ArrayList<Product>(); try { for (int i = 0; i < productCodes.size(); i++) { // if record has been marked for deletion, // don't add to products array list if (!productCodes.get(i).equals(DELETION_CODE)) { Product product = this.getRecord(i); products.add(product); } } }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 79

A class that works with a random-access file (continued) catch(IOException ioe) { ioe.printStackTrace(); return null; } return products; } public Product getProduct(String productCode) { try { int recordNumber = this.getRecordNumber(productCode); Product product = this.getRecord(recordNumber); return product; } catch(IOException ioe) { ioe.printStackTrace(); return null; } }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 80

A class that works with a random-access file (continued) //************************************************* //* Private methods for writing products //************************************************* private boolean writeProduct(Product product, int recordNumber) { try { productsFile.seek(recordNumber * RECORD_SIZE); IOStringUtils.writeFixedString(productsFile, CODE_SIZE, product.getCode()); IOStringUtils.writeFixedString(productsFile, DESCRIPTION_SIZE, product.getDescription()); productsFile.writeDouble(product.getPrice()); return true; } catch(IOException ioe) { ioe.printStackTrace(); return false; } }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 81

A class that works with a random-access file (continued) //************************************************* //* Public methods for writing products //************************************************* public boolean addProduct(Product product) { productCodes.add(product.getCode()); int recordNumber = this.getRecordNumber(product.getCode()); return this.writeProduct(product, recordNumber); } public boolean updateProduct(Product product) { int recordNumber = this.getRecordNumber(product.getCode()); if (recordNumber != -1) return this.writeProduct(product, recordNumber); else return false; }

Murach’s Beg. Java 2, JDK 5, C19 © 2005, Mike Murach & Associates, Inc. Slide 82

A class that works with a random-access file (continued) public boolean deleteProduct(Product product) { int recordNumber = this.getRecordNumber(product.getCode()); if (recordNumber != -1) { productCodes.set(recordNumber, DELETION_CODE); Product p = new Product(DELETION_CODE, "", 0); return this.writeProduct(product, recordNumber); } else return false; } }