Java Programming
Chapter13: File Input and Output
Understanding Computer Files:
- Volatile storage is temporary. Random access memory (RAM) is a temporary storage.
- Nonvolatile storage is permanent storage.
- Computer file exists on permanent storage devices.
- Files can be categorized as two parts: Text files and Binary files.
- Root directory, folders and directories, path delimiter.
Using the Path and Files Classes
- The Path class is to used to create objects that contain information about files and directories.
- The File class is used to perform operations onfiles and directories.
- To use Path and File classes:
Import java.nio.file.*;
Creating a Path
- To create a path, you first determine the default file system by using a statement such as:
FileSystem fs = FileSystems.getDefault();
Without ending s, FileSystem is used to instantiate the object. FilesSystems, is a class that contains factory methods. - After creating a FileSystem object, you can de fine a Path using the getPath():
Path path = fs.getPath(" ");
you can also use FileSystem method getSeparator() to indicate a path delimiter. - You can also use Paths class to create a Path object. You can create a Path object by stating:
Path path = Paths.get(" ");
- After the Path is created, you use its identifier(filePath) to refer to the file.
- Absolute and relative path.
Retrieving Information About a Path
Method | Description |
---|---|
String toString() | Returns the String representation of the Path. |
Path getFileName() | Returns the file or directory denoted by this Path. |
int getNameCount() | Returns the number of name elements in the Path. |
Path getName() | Returns the name in the position of the Path specified by the integer parameter. |
Converting a Relative Path to an Abolute One
- The toAbsolutePath() method converts a relative path to and absolute path. You can use statements like following:
Path fullpath = inputPath.toAbsolutePath();
Checking File Accessibility
-
You can use CheckAccess() method to verify that a file exists. The following import statements enable you to access the constants that can be used as arguments to the method:
import static java.nio.file.AccessMode.*;
-
You can use CheckAccess() method as follows:
filePath.getFileSystem().provider().checkAccess()
-
You can used any of the following as arguments to checkAccess() method:
No argument: checks that the file exists
READ: checks that file exists and that the program has permission to read the file.
WRITE: checks that file exists and that the program has permission to write the file.
EXECUTE: checks that file exists and that the program has permission to excute the file.
Deleting a Path
- The Files class delete() method accepts a Path parameter and delets the last element in the path.
- The Files class deleteIfExists() method also can be used to delete a file, but if the file does not exist, no exception is thrown.
DeterMining File Attributes
-
You can use the readAttributes() method of the Files class to retrieve useful information about a file.
-
It returns an instance of the BasicFileAttributes class, you might create an instance with a statement such as:
BasicFileAttributes attr = Files.readAttributes(filePath, BasicFileAttributes.class);
-
After you create the object, you can used several methods such as size(), creationTime(), lastModifiedTime().
-
Above time methods returns a FileTime object.
-
compareTo() method returns a value of less than 0 if the first FileTime comes before the argument’s FileTime.
time1.compareTo(time2);
File Organization, Stream, and Buffers
- A field is a group of characters that has some meaning.
- A record is a collection of fields that contain data about an entity.
- Records are grouped to create files. Data files consist of related records.
- A data file can be used as a sequential access file when each record is accessed one after another in the order in which it was stored.
- A java application opens a file by creating an object and associating a stream of bytes with it.
- You should always close every file you open.
- When you perform an input operation in an application, you can imagine bytes flowing into your program from an input device through a stream, which functions as a pipeline or channel.
- A buffer describes a memory location where bytes are held after they are logically output but before they are sent to the output device.
- Flushing clears any bytes that have been sent to a buffer for output but have not yet been output to a hardware device.
Using java’s IO Classes
- InputStream, OutputStream, and Reader are subclasses of the Object class. All three of them are abstract.
Class | Description |
---|---|
InputStream | Abstract class that contains methods for performing input |
FileInputStream | Child of InputStream that provides the capability to read from disk files |
BufferedInputStream | Child of FilterInputStream, handles input from a system’s standard input device. |
Output Stream | Abstract class that contains methods for performing input |
FileOutputStream | Child of OutputStream that allows you to write to disk files |
BufferedOutputStream | Child of FilterOutputStream, handles output from a system’s standard output device. |
PrintStream | Child of FilterInputStream, System.out is a PrintStream object |
Reader | Abstract class for reading character streams; Must implement read(char[], int, int) and close(). |
BufferedReader | Reads from a character-input stream, buffering characters to provide efficient reading of characters, arrays, and lines. |
BufferedWriter | Writes text to a character-output stream, buffering characters to provide efficient writing of characters, arrays, and lines. |
OutputStream Method | Description |
---|---|
void close() | Closes the output stream and releases associated system resources. |
void flush() | Flushes the output stream; if any bytes are buffered, they will be written. |
void write(byte[] b) | Writes all the bytes to the output stream from a specific byte array. |
void write(byte[] b, int off, int len) | write bytes to the output stream from the specific byte array starting at offset position off for a length of len characters. |
- Although you have no need to, you can create your own OutputStream object and assign System.out to it.
Writing to a File
- You can construct a BufferedOutputStream object and assign it to the OutputStream in order to assign a file to OutputStream.
- Java lets you assign a file to a Stream object so that screen output and file output work in the same manner.
- You can create a writeable file by using the Files class newOutputStream() method. You pass a Path and a StandardOpenOption argument to this method.
StandardOpenOption | Description |
---|---|
WRITE | Opens the file for writing |
APPEND | Appends new data to the ends of the file; Use this with WRITE or CREATE |
TRUNCATE_EXISTING | Truncates the existing file to 0 bytes. Use this with WRITE |
CREATE_NEW | Creates a new file only if it does not exist |
CREATE | Opens the file if is exist or creates a new file if it does not |
DELETE_ON_CLOSE | Deletes the file when the stream is closed |
- Use following import statements in an application that writes a String of bytes to a file:
import java.nio.file.*;
import java.io.*;
import static java.nio.file.StandardOpenOption.*;
Reading from a File
-
You use InputStream like you use an OutputStream. However, it is more convenient to use Scanner class for keyboard input.
-
You can use the Files class newInputStream() method to open a file for reading. This method accept a Path parameter and returns a stream that can read bytes from a file.
-
If you need to read and display multiple lines from the file, you could use a loop.
BufferedReader Methods | Description |
---|---|
close() | Closes the stream and any resources associated with it |
read() | Reads a single character |
read(char[] buffer, int off, int len) | Reads characters into a portion of an array from position off for len characters |
readLine() | Reads a line of text |
skip(long n) | Skip the specified number of characters |
Creating and Using Sequential Data Files
- Following application reads employee ID numbers, names and pay rates from the key board and sends them to a comma-separated file.
import java.nio.file.*;
import java.io.*;
import static java.nio.file.StandardOpenOption.*;
import java.util.Scanner;
public class WriteEmployeeFile
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
Path file =
Paths.get("Enter your own path");
String s = "";
String delimiter = ",";
int id;
String name;
double payRate;
final int QUIT = 999;
try
{
OutputStream output = new
BufferedOutputStream(Files.newOutputStream(file, CREATE));
BufferedWriter writer = new
BufferedWriter(new OutputStreamWriter(output));
System.out.print("Enter employee ID number >> ");
id = input.nextInt();
while(id != QUIT)
{
System.out.print("Enter name for employee #" + id + " >> ");
name = input.nextLine();
System.out.print("Enter pay rate >> ");
payRate = input.nextDouble();
s = id + delimiter + name + delimiter + payRate;
writer.write(s, 0, s.length());
writer.newLine();
System.out.print("Enter next ID number or " + QUIT + "to quit >> ");
id = input.nextInt();
}
writer.close();
}
catch(Exception e)
{
System.out.println("Message: " + e);
}
}
}
- The BufferedWriter class is the counterpart to BufferedReader.
BufferedWriter Method | Description |
---|---|
close() | Closes the stream, flushing it first |
flush() | Flushes the stream |
newline() | Writes a line separator |
write(String s, int off, int len) | Writes a String from position off for length len |
write(char[] array, int off, int len) | Writes a character array from position off for length len |
write(int c) | Writes a single character |
Learning About Random Access Files
- Business store data in sequential order when they use the records for batch processing, which involves performing the same tasks with many records.
- You can use Java’s FileChannel class to create your own random access files.
FileChannel Method | Description |
---|---|
FileChannel open(Path file, OpenOption… options) | Opens or creates a file, returning a file channel to access the file |
long posistion() | Returns the channel’s file position |
FileChannel position(long newPosition) | Sets the channel’s file position |
int read(ByteBuffer buffer) | Reads a sequence of bytes from the channel into the buffer |
long size() | Returns the size of the channel’s file |
int write(ByteBuffer buffer) | Writes a sequence of bytes to the channel from the buffer |
-
An array of bytes can be wrapped, or encompassed, into a ByteBuffer using the ByteBuffer wrap() method.
-
You can use the Files class newByteChannel() method to get a ByteChannel for a Path, The newByteChannel() method accepts Path and StandardOpenOption arguments that specify how the file will be opened.
-
The ByteChannel returned by the newByteChannel() method then can be cast to a FileChannel using a statement similar to the following:
FileChannel fc = (FileChannel)Files.newByteChannel(File, READ, WRITE);
-
You can create a byte array as follows:
String s = "XYZ";
byte[] data = s.getBytes();
The byte array can be wrapped into a ByteBuffer as follows:
ByteBuffer out = ByteBuffer.wrap(data);
Then the ByteBuffer can be written to the declared FileChannel such as following:
fc.write(out);
-
You can test whether a ByteBuffer’s contents have been used up by checking the hasRemaining() method.
-
After you have written the contens of a ByteBuffer, you can write the same ByteBuffer contents again by using the rewind() method to reposition the ByteBuffer to the beginning of the buffer.
Writing Records to a Random Access Data File
-
You can access the nth record in a FileChannel named fc using the following statement:
fc.position((n - 1) * 50);
-
A key field is the field in a record that makes the record unique from all others.
-
The following statements descrive a byte array is constructed from the String and wrapped into a buffer. Then a file is opened in CREATE mode and a BufferedWriter is established:
String s = " ";
byte[] data = s.getbytes();
ByteBuffer buffer = ByteBuffer.wrap(data);
OutputStream output = new BufferedOutputStream(Files.newOutputStream(file, CREAT));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output));
-
You can use following application to accept any number of records as user input:
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 CreateEmployeeRandomFile
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
Path file =
Paths.get("/Users/sunjingao/Desktop/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);
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);
}
}
}
Reading Records from a Access Data File
Accessing a Random Access File Sequentially
- You can use following statments to access a random access file sequentially:
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;
}
}
Accessing a Random Access File Randomly
- You can use following statments to access a random access file randomly:
While(!idString.parseInt(QUIT))
{
id = Integer.parseInt(toString());
buffer = ByteBuffer.wrap(data);
fc.position(id * RECSIZE);
fc.read(buffer);
s = new String(data);
System.out.println("ID #" + id + " " + s);
System.out.print("Enter ID number or" + QUIT + " to quit >> ");
idString = keyBoard.nextLine();
}