All of Java's file-handling related classes are in the io package. This package includes many classes that enable you to handle files and other types of input and output streams. "File" class is a non-stream class because it just has methods to access the information about a file or directory entry in the filesystem and not the file contents.
To get information about a file and perform standard operations on it,
we should first have a valid File object.
The easiest way to create an instance of File is to pass a filename
to the "File" constructor,
File f = new File("/tmp/hello.txt");
To create file with a relative path
File f = new File( "hello.txt" );
In this case, Java works relative to the current directory of the Java
interpreter. To get the current directory,
(System.getProperty('user.dir')).
You can also create an instance of File by specifying the directory
path and filename as separate String objects:
File f = new File( "/tmp", "hello.txt" );
File class provides methods for :
If the File object is a directory, to list the files in the directory
:
import java.io.*;
class test {
public static void main(String args[]) {
File f = new File(".");
String list[]== f.list(); }
}
list() returns an array of String objects that contains filenames under
the current directory.
createNewFile() - Atomically creates a new, empty file if and only if
a file with this name does not yet exist.
createTempFile(String prefix, String suffix) - Creates an empty file
in the default temporary-file directory, using the given prefix and suffix
to generate its name.
createTempFile(String prefix, String suffix, File directory) - Creates
a new empty file in the specified directory, using the given prefix and
suffix strings to generate its name.
Creating a File object for a nonexistent file is not an error, so File
constructors will not throw any exceptions. You can use the exists() method
to find out the file or directory existence.
We can create a directory with mkdir() or mkdirs().
mkdir() creates a single directory; mkdirs() creates the directory
including any necessary but nonexistent parent directories
Method | Return type | Description |
---|---|---|
canRead() | boolean | Is the file/directory readable? |
canWrite() | boolean | Is the file/directory writable? |
exists() | boolean | Does the file/directory exist? |
getAbsolutePath() | String | Returns the absolute path of the file/directory |
getCanonicalPath() | String | Returns the absolute, case and correct path of the file/directory |
getName() | String | Returns the name of the file/directory |
getParent() | String | Returns the name of the parent directory of the file/directory |
getPath() | String | Returns the path of the file/directory |
isAbsolute() | boolean | Is the filename/directory name absolute? |
isDirectory() | boolean | Is the item a directory? |
isFile() | boolean | Is the item a file? |
isHidden() | boolean | Is the item a hidden file? |
lastModified() | long | Returns the last modification time of the file/directory |
length() | long | Returns the length of the file |
setLastModified(long time) | boolean | Sets the last-modified time of the file or directory |
setReadOnly() | boolean | Marks the file or directory named by this abstract pathname so that only read operations are allowed. |
toString() | String | Returns the pathname string of this abstract pathname. |
toURL() | URL | Converts this abstract pathname into a file: URL. |
File f = new File( "/tmp/test" );
String type = f.isFile();
String name = f.getName();
long len = f.length();
System.out.println(type + name + ", " + len + " bytes " );
Although you can create and delete files and directories, there is no method that allows you to change the current working directory. You have to just create a new "File" object with a different directory for the constructor.
Remember :
32) Write code that uses objects of the
classes InputStreamReader and OutputStreamWriter to translate between Unicode
and either platform default or ISO 8859-1 character encodings.
All fundamental I/O in Java is based on streams. A stream is a sequence of data with undetermined length. It's called a stream because it's like a stream of water that continues to flow. When you are working with terminal input and output, reading or writing files, or communicating through sockets in Java, you are using a stream of one type or another.
InputStream/OutputStream
Abstract classes that define the basic methods for reading/writing
raw bytes of data from a stream. It is the superclass of all other byte
stream classes.
Reader/Writer
Abstract classes that define the basic methods for reading/writing
character streams. It is the superclass of all other character stream classes.
InputStreamReader
Serves as a bridge between byte streams and character streams. It reads
bytes from the input stream and translates them into characters according
to a specified character encoding.
The encoding can be set in the constructor, or you can accept the platform's
default encoding by omitting the encoding identifier.
public class encode {
public static void main(String args[])
{
String p = System.getProperty("file.encoding");
System.out.println(p);
}
}
On my machine, running Java 2 software, this prints out "ISO-8859-1",
which is a code for: ISO Latin-1
A table of encodings can be found at:
http://java.sun.com/products/jdk/1.1/intl/html/intlspec.doc7.html
If you want to specifically translate between a particular encoding
and Unicode, you can use InputStreamReader to do that. One of InputStreamReader's
constructor takes two arguments: the input stream, and the encoding to
use.
For example, the following code fragment will map the characters in the text file referenced through inputFile to Unicode using the ISO 8859-1 encoding, even though the local encoding would have made Java map the characters to a different part of Unicode given the same bit patterns in the text file.
String fileName = "test.txt";
String encodingName = "8859-1";
InputStreamReader in;
try {
FileInputStream inputFile = new FileInputStream(fileName);
in = new InputStreamReader(inputFile, encodingName);
} catch (UnsupportedEncodingException exp1) {
System.out.println(encodingName + " is not a supported encoding scheme.");
} catch (IOException exp2) {
System.out.println("The file " + fileName + " could not be opened.");
}
OutputStreamWriter:
An InputStreamReader acts like a Reader but wraps an underlying InputStream. Likewise, an OutputStreamWriter acts like a Writer but wraps an underlying OutputStream. In the following example, I use an OutputStreamWriter to write a Unicode string to a file.
public void writeString(String filename)
throws IOException {
FileOutputStream fileOut = new FileOutputStream(filename);
OutputStreamWriter out = new OutputStreamWriter(fileOut);
String message = "This is a Unicode string.";
out.write(message);
out.close();
}
Remember :
33) Destinguish between conditions under
which platform default encoding conversion should be used and conditions
under which a specific conversion should be used.
If you are running Java on English Windows platforms, it is probably
Cp1252. If you are running Java on English Solaris platforms, it is most
likely 8859_1.
The bytes in a file are converted to characters using the default character
encoding scheme. If you do not want to use the default encoding scheme,
you need to wrap an InputStreamReader around a FileInputStream.
34) Select valid constructor arguments for FilterInputStream and FilterOutputStream subclasses from a list of classes in the java.io.package.
Filter Streams
The java.io.FilterInputStream and java.io.FilterOutputStream classes
are subclasses of InputStream and OutputStream that acts just like a regular
stream, except that it performs some additional processing on an underlying
data stream. You won't much use these calsses directly. Some of the filtered
streams that are: buffered streams, pushback streams, data streams, and
object streams.
You connect filter streams to an underlying stream that supplies the
actual bytes of data by passing the original stream to the filter stream's
constructor. For example, to create a new DataOutputStream from a FileOutputStream,
FileOutputStream fos = new FileOutputStream("ln.txt");
DataOutputStream dos = new DataOutputStream(fos);
public class FilterInputStream extends InputStream {
protected InputStream in; protected FilterInputStream(InputStream in)
{ this.in = in;} public int read() throws IOException { return in.read();}
public long skip(long n) throws IOException { return in.skip(n);} public
void close() throws IOException { in.close();} Buffering
Buffering is usually used to increase the efficiency of a stream.
public void readFileWithBuffering(String filename) throws IOException
{
FileInputStream fileIn = new FileInputStream(filename);
BufferedInputStream in = new BufferedInputStream(fileIn);
int b;
while ((b = in.read()) != -1)
processByte(b);
in.close();
}
Notice how the BufferedInputStream is "wrapped" around the underlying
stream, a FileInputStream. The first time we call read() on the buffered
stream, it fills an internal buffer from the underlying FileInputStream.
Subsequent calls to read() return data directly from the buffer, which
is faster than reading the file again.
In this example, we've used a default-sized buffer, but there are other
BufferedInputStream constructors that let you specify whatever buffer size
you want.
There's a corresponding output stream class, called BufferedOutputStream.
When you write data using write(), it accumulates the data in an internal
buffer. When the buffer is full, the whole thing is written to the underlying
stream. As we discussed, you can use flush() to force the contents of the
buffer to be written to the underlying stream.
Pushback
Another spiffy filtered stream is PushbackInputStream. This stream
is useful in situations where an application needs to recognize a variety
of file formats. Let's say you have a method for each file format your
application recognizes. You might create a FileInputStream and pass it
to each method. When one of them succeeds without throwing an exception,
you've found the format of the file. However, you'd need to "rewind" the
file stream between each method call so that each method started at the
beginning of the stream. This is where PushbackInputStream comes in handy.
If you discover that you are not reading the format you expected, you can
"push back" any bytes you've read using the unread() method. Subsequent
calls to the PushbackInputStream will return the pushed back data.
Data and Object Streams
The java.io package includes useful filtered streams for reading and
writing primitive types and objects. DataOutputStream, for example, includes
a method for writing each primitive type. These are conveniently named
writeInt(), writeDouble(), writeBoolean(), and so forth. Data written with
a DataOutputStream can be read using a DataInputStream. This class has
a corresponding set of methods named readInt(), readDouble(), readBoolean(),
and so on. The following example shows a pair of methods that demonstrates
use of the data streams.
public void writeData(String filename) throws IOException {
FileOutputStream fileOut = new FileOutputStream(filename);
DataOutputStream out = new DataOutputStream(fileOut);
out.writeInt(9);
out.writeDouble(Math.PI);
out.writeBoolean(true);
out.close();
}
public void readData(String filename) throws IOException {
FileInputStream fileIn = new FileInputStream(filename);
DataInputStream in = new DataInputStream(fileIn);
int i = in.readInt();
double d = in.readDouble();
boolean b = in.readBoolean();
in.close();
System.out.println("Read " + i + ", " + d + ", and " + b + ".");
}
Object streams extend the concept of data streams by allowing you to
read and write entire objects. This is called object serialization; it's
a feature that was introduced in JDK 1.1. On the surface, it's simple,
but underneath, it can get pretty hairy. One of the big complications is
that any objects referenced by an object must also be serialialized. So
when you write an object, all objects it referenced also get written. There
are also some tricky issues involving class resolution when objects are
deserialized.
When it works right, though, it's very simple. Here I present a pair
of methods that write and read a java.awt.Color object. The relevant filtered
stream classes are ObjectOutputStream and ObjectInputStream.
public void writeColor(Color c, String filename) throws IOException
{
FileOutputStream fileOut = new FileOutputStream(filename);
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(c);
out.close();
}
public Color readColor(String filename) throws IOException {
FileInputStream fileIn = new FileInputStream(filename);
ObjectInputStream in = new ObjectInputStream(fileIn);
Color c = null;
try { c = (Color)in.readObject(); }
catch (Exception e) { /* Handle exceptions. */ }
in.close();
return c;
}
Note that the object returned by readObject() must be cast to the correct type.
The FilterInputStream class is the superclass of all of the input stream
classes that filter input. Each of the subclasses of FilterInputStream
works by wrapping an existing input stream, called the underlying input
stream, and providing additional functionality. The methods of FilterInputStream
simply override the methods of InputStream with versions that call the
corresponding methods of the underlying stream.
FilterInputStream cannot be instantiated directly; it must be subclassed.
An instance of one of the subclasses of FilterInputStream is constructed
with another InputStream object. The methods of a subclass of FilterInputStream
should override some methods in order to extend their behavior or provide
some sort of filtering.
FilterInputStream is an abstract decorator:
Filter Stream Classes BufferedInputStream and BufferedOutputStream These classes buffer reads and writes by reading data first into a buffer (an internal array of bytes). Thus an application can read bytes from the stream without necessarily calling the underlying native method. The data is read from or written into the buffer in blocks; subsequent accesses go straight to the buffer. DataInputStream and DataOutputStream These classes read and write primitive Java data types and Strings in a machine-independent way. (Big-endian for integer types, IEEE-754 for floats and doubles, UTF-8 for Unicode) PrintStream The print stream class is implemented by System.out and System.err. It allows very simple printing of both primitive values, objects, and string literals. It uses the platform's default character encoding to convert characters into bytes. This class traps all IOExceptions. This class is primarily intended for debugging. PushbackInputStream This input stream has a one byte pushback buffer so a program can unread the last character read. The next time data is read from the stream, the "unread" character is re-read. GZIPInputStream and GZIPOutputStream From the java.util.zip package, these classes provide compression and decompression services DigestInputStream and DigestOutputStream From the java.util.security package, these classes can calculate a message digest for a stream using a strong hash function like SHA. CipherInputStream and CipherOutputStream From the javax.crypto package in the Java Cryptography Extension (JCE), a standard extension to Java, these classes can calculate encrypt or decrypt streams using a variety of algorithms like DES, RSA, Blowfish, and more. ObjectInputStream and ObjectOutputStream Subclasses of DataInputStream and DataOutputStream that can also serialize and deserialize Java objects to and from raw bytes. Used by remote method invocation (RMI) and JavaBeans. You can also create your own subclasses of FilterInputStream and FilterOutputStream that perform custom filtering.
Buffered Streams The java.io.BufferedInputStream and java.io.BufferedOutputStream classes buffer reads and writes by first storing the in a buffer (an internal array of bytes). Then the program reads bytes from the stream without calling the underlying native method until the buffer is empty. The data is read from or written into the buffer in blocks; subsequent accesses go straight to the buffer. The only real difference to the programmer between a regular stream and a buffered stream are the constructors: public BufferedInputStream(InputStream in) public BufferedInputStream(InputStream in, int size) public BufferedOutputStream(OutputStream out) public BufferedOutputStream(OutputStream out, int size) The size argument is the number of bytes in the buffer. If a size isn't specified, a 512 byte buffer is used. The best size for the buffer is highly platform dependent and generally related to the block size of the disk, at least for file streams. Less than 512 bytes is probably too little and more than 4096 bytes is probably too much. Ideally you want an integral multiple of the block size of the disk. However, you should use smaller buffer sizes for unreliable network connections. For example, URL u = new URL("http://java.developer.com"); BufferedInputStream bis = new BufferedInputStream(u.openStream(), 256);
Data Stream Classes The java.io.DataInputStream and java.io.DataOutputStream classes read and write primitive Java data types and Strings in a machine-independent way. Generally you use a DataInputStream to read data written by a DataOutputStream. This format uses IEEE 754 for floating point data, big-endian format for integer data, and a modified UTF-8 for Unicode data. DataOutputStream declares these methods: public DataOutputStream(OutputStream out) public synchronized void write(int b) throws IOException public synchronized void write(byte[] data, int offset, int length) throws IOException public final void writeBoolean(boolean b) throws IOException public final void writeByte(int b) throws IOException public final void writeShort(int s) throws IOException public final void writeChar(int c) throws IOException public final void writeInt(int i) throws IOException public final void writeFloat(float f) throws IOException public final void writeDouble(double d) throws IOException public final void writeBytes(String s) throws IOException public final void writeChars(String s) throws IOException public final void writeUTF(String s) throws IOException public final int size() public void flush() throws IOException The size() method returns the number of bytes written to this data output stream.
DataInputStream Generally you use a DataInputStream to read data written by a DataOutputStream. This format uses IEEE 754 for floating point data, big-endian format for integer data, and a modified UTF-8 for Unicode data. DataInputStream has these methods: public DataInputStream(InputStream in) public final int read(byte[] input) throws IOException public final int read(byte[] input, int offset, int length) throws IOException public final void readFully(byte[] input) throws IOException public final void readFully(byte[] input, int offset, int length) throws IOException public final int skipBytes(int n) throws IOException public final boolean readBoolean() throws IOException public final byte readByte() throws IOException public final int readUnsignedByte() throws IOException public final short readShort() throws IOException public final int readUnsignedShort() throws IOException public final char readChar() throws IOException public final int readInt() throws IOException public final long readLong() throws IOException public final float readFloat() throws IOException public final double readDouble() throws IOException public final String readUTF() throws IOException public static final String readUTF(DataInput in) throws IOException The readFully() methods read repeatedly from the underlying stream until the byte array is filled. This contrasts with the regular read() methods which only read as many bytes as are available at the moment. There's also a fairly common readLine() method that was used quite commonly in Java 1.0. However it's deprecated in favor of BufferedReader in Java 1.1
Print Streams The java.io.PrintStream class is a subclass of FilterOutputStream. It is implemented by System.out and System.err. It allows very simple printing of both primitive values, objects, and string literals. It uses the platform's default character encoding to convert characters into bytes. This class traps all IOExceptions. However you can test the error status with checkError(). This returns true if an error has occurred, false otherwise. public boolean checkError() The main use of the class is the exceptionally overloaded print() and println() methods. They differ in that println() adds an end-of-line character to whatever it prints while print() does not. public void print(boolean b) public void print(int i) public void print(long l) public void print(float f) public void print(double d) public void print(char s[]) public void print(String s) public void print(Object obj) public void println() public void println(boolean x) public void println(char x) public void println(int x) public void println(long x) public void println(float x) public void println(double x) public void println(char x[]) public void println(String x) public void println(Object x) PrintStream is primarily intended for debugging. Otherwise it's unofficially deprecated in Java 1.1. You should use the PrintWriter class instead
PushbackInputStream The PushbackInputStream class provides a pushback buffer so a program can "unread" bytes onto the stream. These may be bytes the program has read from the stream or they may be bytes that come from somewhere else. The next time data is read from the stream, the "unread" bytes are read. public void unread(int b) throws IOException public void unread(byte[] data, int offset, int length) throws IOException public void unread(byte[] data) throws IOException By default the buffer is only one byte long, and trying to unread more than that throws an IOException. However you can change the default buffer size with the second constructor below: public PushbackInputStream(InputStream in) public PushbackInputStream(InputStream in, int size) Although both PushbackInputStream and BufferedInputStream use buffers, only a PushbackInputStream allows unreading and only a BufferedInputStream allows marking and resetting. In a PushbackInputStream markSupported() returns false. public boolean markSupported() The read() and available() methods work exactly as with normal input streams. However, they first attempt to read from the pushback buffer. public int read() throws IOException public int read(byte[] data, int offset, int length) throws IOException public int available() throws IOException
35) Write appropriate code to read, write and update files using FileInputStream, FileOutputStream, and RandomAccessFile objects.
If you want to directly specify encodings, one way of doing so is illustrated by the following program, which writes all the lower case letters of the Unicode alphabet to a file. Some of these characters have a non-zero high byte (that is, they are greater in value than '\u00ff'), and preserving both bytes of the character is therefore important. The encoding used is one called UTF-8, which has the property of representing ASCII text as itself (one byte), and other characters as two or three bytes.
import java.io.*;
public class enc1 {
public static void main(String args[])
{
try {
FileOutputStream fos = new FileOutputStream("out");
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF8");
for (int c = '\u0000'; c <= '\uffff'; c++) {
if (!Character.isLowerCase((char)c)) continue;
osw.write(c);
}
osw.close();
}
catch (IOException e) {
System.err.println(e);
}
}
}
This program reverses the process:
import java.io.*;
public class enc2 {
public static void main(String args[])
{
try {
FileInputStream fis = new FileInputStream("out");
InputStreamReader isr = new InputStreamReader(fis, "UTF8");
for (int c = '\u0000'; c <= '\uffff'; c++) {
if (!Character.isLowerCase((char)c)) continue;
int ch = isr.read();
if (c != ch) System.err.println("error");
}
isr.close();
}
catch (IOException e) {
System.err.println(e);
}
}
}
InputStreamReader and OutputStreamWriter are the classes where byte streams are converted to character streams and vice versa. This issue is quite an important one if you are concerned with writing applications that operate in an international context.
RandomAccessFile
In addition to all of the Stream classes, there exists a class RandomAccessFile
that can be used to seek through files with fixed-length records. RandomAccessFile
doesnot work with any of the stream filters. Therefore, you can't use it
to seek inside any other Stream.
36) Describe the permanent effects on the file system of constructing and using FileInputStream, FileOutputStream, and RandomAccessFile objects.
Copyright © 1999-2000, Jyothi Krishnan
All Rights Reserved.