Friday 2 April 2010

File Handling and Input/Output

java.io package
Classes related to input and output are present in the JavaTM language package java.io . Java technology uses "streams" as a general mechanism of handling data. Input streams act as a source of data. Output streams act as a destination of data.
File class
The file class is used to store the path and name of a directory or file. The file object can be used to create, rename, or delete the file or directory it represents. The File class has the following constructors - File(String pathname); // pathname could be file or a directory name File(String dirPathname, String filename); File(File directory, String filename); The File class provides the getName() method which returns the name of the file excluding the directory name. String getName();
Byte Streams
The package java.io provides two set of class hierarchies - one for handling reading and writing of bytes, and another for handling reading and writing of characters. The abstract classes InputStream and OutputStream are the root of inheritance hierarchies handling reading and writing of bytes respectively. Figure : InputStream class hierarchy (partial) Figure : OutputStream class hierarchy (partial)
read and write methods
InputStream class defines the following methods for reading bytes - int read() throws IOExceptionint read(byte b[]) throws IOExceptionint read(byte b[], int offset, int length) throws IOException Subclasses of InputStream implement the above mentioned methods. OutputStream class defines the following methods for writing bytes - void write(int b) throws IOExceptionvoid write(byte b[]) throws IOExceptionvoid write(byte b[], int offset, int length) throws IOException Subclasses of OutputStream implement the above mentioned methods. The example below illustrates code to read a character. //First create an object of type FileInputStream type using the name of the file.FileInputStream inp = new FileInputStream("filename.ext");//Create an object of type DataInputStream using inp.DataInputStream dataInp = new DataInputStream(inp);int i = dataInp.readInt();
Reader and Writer classes(l.w. = chr = character and last r = reader )
Similar to the InputStream and OutputStream class hierarchies for reading and writing bytes, Java technology provides class hierarchies rooted at Reader and Writer classes for reading and writing characters. A character encoding is a scheme for internal representation of characters. Java programs use 16 bit Unicode character encoding to represent characters internally. Other platforms may use a different character set (for example ASCII) to represent characters. The reader classes support conversions of Unicode characters to internal character shortage. Every platform has a default character encoding. Besides using default encoding, Reader and Writer classes can also specify which encoding scheme to use.The Reader class hierarchy is illustrated below. The Writer class hierarchy is illustrated below. The table below gives a brief overview of key Reader classes.
CharArrayReaderThe class supports reading of characters from a character array.
InputStreamReaderThe class supports reading of characters from a byte input stream. A character encoding may also be specified.
FileReaderThe class supports reading of characters from a file using default character encoding.
The table below gives a brief overview of key Writer classes.
CharArrayWriterThe class supports writing of characters from a character array.
OutputStreamReaderThe class supports writing of characters from a byte output stream. A character encoding may also be specified.
FileWriterThe class supports writing of characters from a file using default character encoding.
The example below illustrates reading of characters using the FileReader class. //Create a FileReader class from the file name.FileReader fr = new FileReader("filename.txt");int i = fr.read(); //Read a character

Threads

Threads
A thread is in process in execution within a program. Within a program each thread defines a separate path of execution.
Creation of a thread
A thread can be created in two ways a) By implementing the Runnable interface. The Runnable interface consists of only one method - the run method. The run method has a prototype of public void run(); b) By extending the class Thread.
Execution of a thread
To execute a thread, the thread is first created and then the start() method is invoked on the thread. Eventually the thread would execute and the run method would be invoked. The example below illustrates the two methods of thread creation. You should note that the run method should not be invoked directly.

public class ThreadExample extends Thread {
public void run() {
System.out.println("Thread started");
}
public static void main(String args[]) {
ThreadExample t = new ThreadExample();
t.start();
}
}
Example - Creation of Thread by extending the
Thread class.
When the run method ends, the thread is supposed to "die". The next example shows the creation of thread by implementing the Runnable interface.

public class ThreadExample2 implements Runnable {
public void run() {
.../* Code which gets executed when
thread gets executed. */
}
public static void main(String args[]) {
ThreadExample2 Tt = new ThreadExample2();
Thread t = new Thread(Tt);
t.start();
}
}

Example - Creating thread by implementing Runnable
States of thread
A thread can be in one of the following states - ready, waiting for some action, running, and dead. These states are explained below. Running State A thread is said to be in running state when it is being executed. This thread has access to CPU. Ready State A thread in this state is ready for execution, but is not being currently executed. Once a thread in the ready state gets access to the CPU, it gets converted to running state. Dead State A thread reaches "dead" state when the run method has finished execution. This thread cannot be executed now.Waiting State In this state the thread is waiting for some action to happen. Once that action happens, the thread gets into the ready state. A waiting thread can be in one of the following states - sleeping, suspended, blocked, waiting for monitor. These are explained below.
Yielding to other processes
A CPU intensive operation being executed may not allow other threads to be executed for a "large" period of time. To prevent this it can allow other threads to execute by invoking the yield() method. The thread on which yield() is invoked would move from running state to ready state.
Sleep state of a thread
A thread being executed can invoke the sleep() method to cease executing, and free up the CPU. This thread would go to the "sleep" state for the specified amount of time, after which it would move to the "ready" state. The sleep method has the following prototypes.

public static void sleep (long millisec) //sleep for millisec
throws InterruptedException;
public static void sleep (long millisec, int nanosec) //sleep for x millisec
throws InterruptedException; // and y nanoseconds
Synchronized state
A code within the synchronized block is "atomic". This means only one thread can execute that block of code for a given object at a time. If a thread has started executing this block of code for an object, no other thread can execute this block of the code (or any other block of synchronized code) for the same object.

public synchronized void synchExample() {
/* A set of synchronized statements. Assume
here that x is a data member of this class. */
if(x == 0)
x = 1;
}