Course List: http://www.c-jump.com/bcc/
Sequential access to files
Access records sequentially from beginning to end
Good for batch processing
Same tasks with many records one after the other
Inefficient for many applications
Realtime applications
Require immediate record access while client waits
Random access to files
Records can be located in any order
Also called direct access or instant access files
A pointer has to be set prior to reading/writing a record
java.nio.channels.FileChannel and java.io.RandomAccessFile classes:
Both classes allow reading and writing a file
Program can search for a specific location in a file. Read/write operations will start at a specific position.
Class java.nio.channels.FileChannel represents a channel for reading and writing a file
To access Nth record, call
fc.position( ( N - 1 ) * RECORD_SIZE_IN_BYTES );
where N is 1, 2, 3, ...
Note that
(a) records are numbered starting at 0 offset
(b) all records must be of the same length.
Class java.nio.ByteBuffer helper object represents a sequence of raw bytes
wrap() method wraps a byte array into a ByteBuffer object:
String str = "XYZ"; byte[] data = str.getBytes(); ByteBuffer out = ByteBuffer.wrap( data );
FileChannel object can then write the ByteBuffer into the file:
fc.write( out );
import java.nio.file.*; import java.io.*; import java.nio.channels.FileChannel; import java.nio.ByteBuffer; import static java.nio.file.StandardOpenOption.*; public class RandomAccessTest { public static void main(String[] args) { Path file = Paths.get("C:/example/mydata.txt"); String s = "XYZ"; byte[] data = s.getBytes(); ByteBuffer out = ByteBuffer.wrap(data); FileChannel fc = null; try { fc = (FileChannel)Files.newByteChannel(file, CREATE, WRITE); // starting at the beginning of the file fc.position(0); // as long as there are bytes in the buffer, while(out.hasRemaining()) { // write sequence of bytes from the buffer fc.write(out); } // reset the buffer position back to the beginning out.rewind(); // reposition the file location at offset 22 // NOTE: the unfilled gaps are stored as zero bytes fc.position(22); // as long as there are bytes in the buffer, while(out.hasRemaining()) { // write sequence of bytes from the buffer fc.write(out); } // reset the buffer position back to the beginning out.rewind(); // reposition the file location at offset 12 fc.position(12); while(out.hasRemaining()) { // write sequence of bytes from the buffer fc.write(out); } fc.close(); } catch (Exception e) { System.out.println("Error message: " + e); } } } // class RandomAccessTest
// Using BufferedWriter.write(), program creates a file with 10 records: // // 000, ,00.00 // 000, ,00.00 // ... // 000, ,00.00 // import java.nio.file.*; import java.io.*; import java.nio.ByteBuffer; import static java.nio.file.StandardOpenOption.*; public class CreateEmptyEmployeesFile { public static void main(String[] args) { Path file = Paths.get("C:\\example\\RandomEmployees.txt"); String s = "000, ,00.00" + System.getProperty("line.separator"); byte[] data = s.getBytes(); ByteBuffer buffer = ByteBuffer.wrap(data); final int NUMRECS = 10; try { OutputStream output = new BufferedOutputStream(Files.newOutputStream(file, CREATE)); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output)); for(int count = 0; count < NUMRECS; ++count) writer.write(s, 0, s.length()); writer.close(); } catch(Exception e) { System.out.println("Error message: " + e); } } }//class CreateEmptyEmployeesFile
// Store record at a specific location in a file import java.nio.file.*; import java.io.*; import java.nio.channels.FileChannel; import java.nio.ByteBuffer; import static java.nio.file.StandardOpenOption.*; public class CreateOneRandomAccessRecord { public static void main(String[] args) { Path file = Paths.get("C:\\example\\RandomEmployees.txt"); String s = "002,Janitor,12.25" + System.getProperty("line.separator"); final int RECSIZE = s.length(); byte[] data = s.getBytes(); ByteBuffer buffer = ByteBuffer.wrap(data); FileChannel fc = null; try { fc = (FileChannel)Files.newByteChannel(file, READ, WRITE); fc.position(2 * RECSIZE); fc.write(buffer); fc.close(); } catch (Exception e) { System.out.println("Error message: " + e); } } }//class CreateOneRandomAccessRecord
// Get record data from the user // Store record at a specific location in a file import java.nio.file.*; import java.io.*; import java.nio.channels.FileChannel; import java.nio.ByteBuffer; import static java.nio.file.StandardOpenOption.*; import java.util.Scanner; public class CreateEmployeesRandomFile { public static void main(String[] args) { Scanner input = new Scanner(System.in); Path file = Paths.get("C:\\example\\RandomEmployees.txt"); String s = "000, ,00.00" + System.getProperty("line.separator"); final int RECSIZE = s.length(); FileChannel fc = null; String delimiter = ","; String idString; int id; String name; String payRate; final String QUIT = "999"; try { fc = (FileChannel)Files.newByteChannel(file, READ, WRITE); System.out.print("Enter employee ID number >> "); idString = input.nextLine(); while(!(idString.equals(QUIT))) { id = Integer.parseInt(idString); System.out.print("Enter name for employee #" + id + " >> "); name = input.nextLine(); System.out.print("Enter pay rate >> "); payRate = input.nextLine(); s = idString + delimiter + name + delimiter + payRate + System.getProperty("line.separator"); byte[] data = s.getBytes(); ByteBuffer buffer = ByteBuffer.wrap(data); // The records are stored pre-sorted based on the specified ID: fc.position(id * RECSIZE); fc.write(buffer); System.out.print("Enter next ID number or " + QUIT + " to quit >> "); idString = input.nextLine(); } fc.close(); } catch (Exception e) { System.out.println("Error message: " + e); } } }//class CreateEmployeesRandomFile
Reading random access files can be done either sequentially or randomly
Sequential access benefits:
no need to use random access file
instead, read records, sort records, display records
Random access benefits:
retrieve specific record from file directly -- no need to read any other records
constraint: must use unique key field to locate the record
// Read through all records in RandomEmployees.txt file sequentially // if ID number is zero, skip and assume no user record was entered/stored there import java.nio.file.*; import java.io.*; import static java.nio.file.AccessMode.*; public class ReadEmployeesSequentially { public static void main(String[] args) { Path file = Paths.get("C:\\example\\RandomEmployees.txt"); String[] array = new String[3]; String s = ""; String delimiter = ","; int id; String stringId; String name; double payRate; double gross; final double HRS_IN_WEEK = 40; double total = 0; try { InputStream input = new BufferedInputStream(Files.newInputStream(file)); BufferedReader reader = new BufferedReader(new InputStreamReader(input)); System.out.println(); s = reader.readLine(); while(s != null) { array = s.split(delimiter); stringId = array[0]; id = Integer.parseInt(array[0]); if(id != 0) { name = array[1]; payRate = Double.parseDouble(array[2]); gross = payRate * HRS_IN_WEEK; System.out.println("ID#" + stringId + " " + name + " $" + payRate + " $" + gross); total += gross; } s = reader.readLine(); } reader.close(); } catch(Exception e) { System.out.println("Message: " + e); } System.out.println(" Total gross payroll is $" + total); } }//class ReadEmployeesSequentially
// ask user for an employee ID number // calculate correct record position in the data file (one less than the ID number) // position the file pointer at the record location for reading // read the record import java.nio.file.*; import java.io.*; import java.nio.channels.FileChannel; import java.nio.ByteBuffer; import static java.nio.file.StandardOpenOption.*; import java.util.Scanner; public class ReadEmployeesRandomly { public static void main(String[] args) { Scanner keyBoard = new Scanner(System.in); Path file = Paths.get("C:\\example\\RandomEmployees.txt"); String s = "000, ,00.00" + System.getProperty("line.separator"); final int RECSIZE = s.length(); byte[] data = s.getBytes(); ByteBuffer buffer = ByteBuffer.wrap(data); FileChannel fc = null; String idString; int id; final String QUIT = "999"; try { fc = (FileChannel)Files.newByteChannel(file, READ, WRITE); System.out.print("Enter employee ID number or " + QUIT + " to quit >> "); idString = keyBoard.nextLine(); while(!idString.equals(QUIT)) { id = Integer.parseInt(idString); buffer= ByteBuffer.wrap(data); // Locate record based on the ID: fc.position(id * RECSIZE); fc.read(buffer); s = new String(data); System.out.println("ID #" + id + " " + s); System.out.print("Enter employee ID number or " + QUIT + " to quit >> "); idString = keyBoard.nextLine(); } fc.close(); } catch (Exception e) { System.out.println("Error message: " + e); } } }//class ReadEmployeesRandomly
Class java.io.RandomAccessFile provides random access to a file for reading and/or writing
Constructors of the RandomAccessFile class:
Constructor Throws ---------------------------------- ---------------------- RandomAccessFile(File, stringMode) FileNotFoundException RandomAccessFile(stringPathName, stringMode) FileNotFoundException
Access mode values:
"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. Updates to file content or metadata written synchronously to storage device
"rwd" -- Open for reading and writing. Updates to file content written synchronously to the storage device
Notes:
The "rwd" mode forces writes to be synchronous with the physical media, which can be a very slow mode.
Latest RandomAccessFile implementation uses the NIO ( Java New IO ) classes in its implementation -- FileChannel and FileDescriptor.
Original RandomAccessFile implementation lacked buffering; BufferedReader has much better performance
FileChannel uses NIO buffers; however, it lacks the readLine() method
In general, it is best to use a buffered sequential access (like BufferedReader) whenever possible.
// Open a file for reading with Files.newInputStream() method, which // returns a stream that can read bytes from a file import java.nio.file.*; import java.io.*; public class ReadFile { public static void main(String[] args) { Path file = Paths.get( "C:/example/myfile.txt" ); InputStream input = null; try { input = Files.newInputStream( file ); BufferedReader reader = new BufferedReader( new InputStreamReader( input ) ); String str = null; str = reader.readLine(); System.out.println( str ); input.close(); } catch ( IOException ex ) { System.out.println( ex ); } } }
How to create a read-write RandomAccessFile object
RandomAccessFile myFile = new RandomAccessFile("myfile.dat", "rw");
How to create a read-only RandomAccessFile object
RandomAccessFile myFile = new RandomAccessFile("myfile.dat", "r");
How to create a synchronized read-write object
RandomAccessFile myFile = new RandomAccessFile("myfile.dat", "rws");
Class java.io.RandomAccessFile implements two interfaces:
Methods of the RandomAccessFile class for input and output
Method Throws --------------- ------------- seek(long) IOException length() IOException setLength(long) IOException close() IOException
With setLength() the length of the file can be changed, resulting in the content to be truncated or exatended.
Code that writes data to a file
RandomAccessFile booksFile = new RandomAccessFile("books.ran", "rw"); // write 3 records that contain 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++) { booksFile.writeChars(codes[i]); booksFile.writeDouble(prices[i]); } booksFile.close();
Code that reads data from a file
final int RECORD_LENGTH = 16; // 4 chars @ 2 bytes per
// char +1 double @ 8
// bytes
RandomAccessFile booksFile =
new RandomAccessFile("books.ran", "r");
// move the pointer to the third record
int recordNumber = 3;
booksFile.seek((recordNumber - 1) * RECORD_LENGTH);
// read the third record
String code = "";
for (int i = 0; i < 4; i++)
code += booksFile.readChar();
double price = booksFile.readDouble();
booksFile.close();
import java.io.*; // Utility class for reading/writing Strings of fixed length padded with zeroes public class IOStringUtils { // out parameter is a RandomAccessFile object // length is the size of the fixed length string to be written 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 } } // in parameter is a RandomAccessFile object public static String readFixedString( 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(); } }//class IOStringUtils