communication path. If your program is writing to a stream, it is the stream's source. If it is reading from a stream, it is the stream's destination.
The communication path is dependent on the type of I/O being performed. It can consist of memory-to-memory transfers, file system, network, and other forms of I/O.
A Stream is an abstract representation of an input or output device that is a source of or destination for data. The java.io package supports two types of streams, Binary Streams, which contain binary data, and character streams, which contain character data.
When you write data to a stream as a series of bytes, that is binary data, it is written to the stream exactly as it appears in memory. No transformation of the data takes place. Numerical values are just written as a series of bytes.
Character streams are used for storing and retrieving text. You can also use character streams to read a text file not written by a java program.
All numeric values are converted to a textual representation before written to the stream. This involves formatting the data to generate a character representation of the data value.
All Unicode Characters are automatically converted to the local representation of the characters as used by the host machine and then these are written to the file.
Unicode uses 16 bits to represent each character. If the high-order 9 bits are all zeros, then the encoding is simply standard ASCII, otherwise the bits represents a character that is not represented in 7-bit ASCII. Java’s char datatype uses Unicode Encoding.
Unicode’s 16-bit is sufficient to encode most alphabets but pictographic Asian Languages like Japanese, Vietnamese present a problem. The answer for this is UTF (UCS Transformation format and UCS stands for Universal Character Set).
UTF encoding uses as many bits as needed to encode a character: fewer bits for smaller alphabets and more bits for larger Asian alphabets.
The important classes in the io.package are
a) File – An object of this class represents a pathname either to a file that you will access for input or output or to a directory.
b) RandomAccessFile – Random Access to a File.
c) Output Stream – Base class for Byte Stream output.
d) Input Stream – Base Class for Byte Stream Input.
e) Writer – Base class for Character stream Output.
f) Reader – Base class for Character stream Input.
- Streams are powerful because they abstract away the details of the communication path from input and output operations. This allows all I/O to be performed using a common set of methods.
- Whenever we are using the classes of the java.io package, the package will have to be imported and all the codes should be put in a try - catch block or the method should have throws signature, because most of the methods in this package throw IOException which is a Checked Exception.
File Class
File class represents the name of a file or directory that might exist on the hose machine’s file system.
The constructors are 1. File (String file)
2. File(String dir, String subpath) 3. File(File dir, String subpath)
"File" class is a non-stream class because it just has methods to access the information about a file or directory entry in the file system 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 important methods are:
1. Boolean exists() – Where the file or directory exists or not
2. String getAbsolutePath() – This returns the absolute and not the relative path of file or directory.
3. String getName()
4. String getParent() – This returns the name of the directory that contains the File.
5. Boolean isDirectory() 6. Boolean isFile()
7. String [ ] list() – This returns an array containing the name of files and directories within the File (which should be a directory).
8. Boolean canRead()
9. Boolean canWrite() 10. long length()
11. Boolean mkdir(File f)
12. boolean renameTo (File newname)
Creating a file or 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
renaming a file
renameTo(File dest) - Renames the file/directory denoted by this abstract pathname.
deleting a file or directory
delete() to delete a file or directory.
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.
IMP: Deleting an instance of the File has no effect on the local file system
IMP: Please note that the File class objects created are of a directory present in the system and for checking the same, please change it to a directory present in your system along with the file.
Code (Simple methods of the File class) import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class File1 {
File f;
public File1() throws IOException {
f= new File("C:/Students-March","test.txt");
System.out.println("Chek for the file " +f.exists());
System.out.println("Chek for the file " +f.getName());
System.out.println("Chek for the file " +f.getParent());
System.out.println("Chek for the file " +f.isFile());
System.out.println("Chek for the file" +f.isDirectory());
}
public static void main(String args[]) throws IOException {
new File1();
} }
Code (Example of the list method of the File class) import java.awt.*;
import java.io.*;
import java.awt.event.*;
public class File2 implements ActionListener {
f1.setLayout(new FlowLayout());
ta = new TextArea(10,20);
tf.addActionListener(this);
b.addActionListener(this);
f1.setSize(200,200);
f1.setVisible(true);
}
catch(Exception ie)
{
ie.printStackTrace();
} }
public void actionPerformed(ActionEvent ae) {
if(ae.getSource()==b) {
String s = tf.getText();
File f = new File(s);
if (f.isDirectory())
{
String arr[]= f.list();
for( int i=0;i<arr.length;i++)
{
ta.append(""+arr[i]+"\n");
} }
else if(f.isFile())
{
ta.append("Please enter directory name");
} }
}
public static void main(String[] args) {
new File2();
} }
RandomAccessFile Class
One way to ready or modify a file is to use the RandomAccessFile class. This class represents a model of files that is incompatible with the Stream / Writer classes.
With a RandomAccessFile, you can seek a desired position within a file and then read or write a desired amount of data. The RandomAccessFile provides method that support seeking, reading and writing
Constructors
RandomAccessFile (String file, String mode // which can be ‘r’ or ‘rw’) The rw refers to Read - Write over here.
The ‘rw” form of constructor is useful when you want to open some of the methods of the File class before opening a RAF, so that a instance of File is in hand when calling the RAF constructor.
Constructing a RAF is similar like constructing an instance of File.
After a random Access file is created, you can seek to any byte position within the file and then read or write. Pre java systems have supported this seeing to a position relative to the beginning of the file, end of the file or the current position of the file. The methods
long getFilePointer () throws IOException – This returns the current position within the file, in bytes, Subsequent reading and writing will take place starting at this position.
long length() throws – length of file in bytes
void seek( long position) thro – This sets the current position within the file in bytes. Subsequent reading and writing will take place at this position. Files start at position 0.
The common methods that support reading and writing are:
int read() - this returns the next byte from the file or –1 is end of file int read(byte d[]) – attempts to read enough bytes t fill array d[]
int read(byte d[], int o, int n) – attempts to read n number of bytes into array d[] starting at o.
RandomAccessFile supports reading and writing of all primitive data types.
When RAF is no longer needed, it should be closed:
void close() throws IOException Code
import java.awt.*;
import java.io.*;
public class Raf1 {
RandomAccessFile raf ;
public Raf1()
{ try {
raf = new RandomAccessFile("1.txt","rw");
raf.writeBoolean(true);
raf.writeChar('a');
raf.writeInt(1234);
System.out.println("read1"+raf.length());
raf.seek(1);
System.out.println("read1"+raf.readChar());
System.out.println("read1"+raf.readInt());
raf.seek(0);
System.out.println("read1"+raf.readBoolean());
}
catch(Exception e)
{
e.printStackTrace();
} }
public static void main(String[] args) {
new Raf1();
}
}
Stream Classes
The superclass of the Stream Classes or called as the byte oriented classes are the abstract class InputStream and OutputStream. We will be discussing each of the important classes relevant from the certification point over here.
FileInputStream
This class will enable us to create a InputStream with which one can use to read bytes from a file.
The common Constructors are as under:
FileInputStream (String filename);
FileInputStream (File f);
Either of this will throw a checked exception and hence will have to be put in a try / catch block or the method will have to throw this FileNotFoundException.
Code
import java.io.*;
public class Fis1 {
public static void main(String[] args) {
try
{
File f =new File(args[0]);
FileInputStream fis = new FileInputStream(f);
int i = fis.available();
for(int j=0;j<i;j++) {
System.out.print((char)fis.read());
}
}
catch(Exception e)
{
e.printStackTrace();
}
} }
Code
import java.io.*;
public class Fis2 {
public static void main(String[] args) {
try
{
File f =new File(args[0]);
FileInputStream fis = new FileInputStream(f);
int i;
while((i = fis.read())!=-1) {
System.out.print((char)i);
}
In the earlier two codes, we have seen how to use the while and the for loop for using the read () method and then printing out the contents of the file which we pass as argument to the code.
ByteArrayInputStream
This is an implementation of an InputStream that uses byte array as the source.
The two constructors for this are:
ByteArrayInputStream (byte b[])
ByteArrayInputStream (byte b[], int start, int noofbytes) Code
import java.io.*;
public class BAIS {
public static void main(String[] args) {
try {
String s = "hello is it done?";
byte b[] = s.getBytes();
ByteArrayInputStream bais = new ByteArrayInputStream(b);
int i;
while((i=bais.read())!=-1) {
System.out.print((char)i);
} }
catch (Exception ie)
{
ie.printStackTrace();
} } }
SequenceInputStream
This class allows us to concatenate two Input Streams.
The two constructors for this are:
SequenceInputStream (IS one, IS two); Remember it can take only two Input Streams.
SequenceInputStream (Enumeration s)
In the case of the first constructor, the class reads requests from the first until it runs out and then switches to the other and so on.
In the case of Enumeration, it will continue through all the IS until the end of the last one is reached.
Code
import java.io.*;
public class SIS {
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("1.txt");
FileInputStream fis1 = new FileInputStream("2.txt");
SequenceInputStream sis = new SequenceInputStream(fis,fis1);
int i;
while((i=sis.read())!=-1) {
System.out.print((char)i);
} }
catch (IOException ie)
{
ie.printStackTrace();
} } }
Filter Streams
The FilterInputStream and 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.
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.
You won't much use these classes directly. Some of the filtered streams that are:
1. Buffered streams 2. Data streams 3. Print Stream
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);
Buffered Streams
Buffering is usually used to increase the efficiency of a stream.
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. The BufferedInputStream constructors let you specify whatever buffer size you want.
Data Streams
The Date Stream a type of filtered streams is for reading and writing primitive types and objects in a portable way.
It gives you access to a range of methods such as readDouble, readInt that will work the same on different platforms. In JDK1.0 this was one of the main ways to access Unicode text, but has been superceded by the Reader classes since JDK 1.1. These classes take an instance of a Stream as a constructor
These are conveniently named writeInt(), writeDouble(), writeBoolean(), and so forth. Data written with a DataOutputStream can be read using a DataInputStream using the readInt(), readDouble() and readBoolean() etc.
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 primitive values, objects, and string literals. It uses the platform's default character encoding to convert characters into bytes. This class traps all IOException.
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.
Code
import java.io.*;
public class DIS
{
public static void main(String[] args) {
try {
FileOutputStream fos = new FileOutputStream("3.txt");
DataOutputStream dos = new DataOutputStream(fos);
dos.writeInt(10) ;
dos.writeDouble(10.10);
dos.writeBoolean(true);
dos.close();
fos.close();
FileInputStream fis = new FileInputStream("3.txt");
DataInputStream dis = new DataInputStream(fis);
System.out.println(""+dis.readInt());
System.out.println(""+dis.readDouble());
System.out.println(""+dis.readBoolean());
}
catch (IOException ie)
{
ie.printStackTrace();
} } }
FileOutputStream
The FileOutputStream is used to create an OutputStream that u can use to write bytes to a file.
The most common used constructors are:
FileOutputStream (String s) FileOutputStream (File f)
FileOutputStream (String s, boolean append)
This class can throw IOException or SecurityException.
IMP: Creating of a file is not dependent on whether the file is already existing or not. This will create another file and incase there is a existing file, the same will be overwritten.
Code
import java.io.*;
public class FOS1 {
public static void main(String[] args) {
try {
String s= "appending here";
byte b[] =s.getBytes();
FileOutputStream fos = new FileOutputStream("1.txt",true);
for(int i=0; i<b.length;i++) {
fos.write(b[i]);
}
fos.close();
}
catch (IOException ie)
{
ie.printStackTrace();
} } }
Character Classes
The Streams basically was dealing with bytes and hence the Reader and Writer classes was introduced which is also called as Character Oriented Streams.
The important Reader Classes from the Certification point of view are a) File Reader
b) BufferedReader
Both the above classes are similar to the byte oriented streams.
Code
import java.io.*;
public class FReader {
public static void main(String[] args) {
try {
FileReader fr= new FileReader("1.txt");
FileWriter fw = new FileWriter("5.txt");
int i;
while ((i=fr.read())!=-1)
{
System.out.print((char)i);
} }
catch (IOException ie)
{
ie.printStackTrace();
} } }
Corresponding to the Reader classes, the important classes from the certification point of view are
a) FileWriter b) BufferedWriter Code
import java.io.*;
public class FReader {
public static void main(String[] args) {
try {
FileReader fr= new FileReader("1.txt");
FileWriter fw = new FileWriter("5.txt");
int i;
while ((i=fr.read())!=-1)
{
System.out.print((char)i);
} }
catch (IOException ie)
{
ie.printStackTrace();
} } }
Code
import java.io.*;
public class ISReader {
public static void main(String[] args) {
try {
System.out.println("Enter the first number ");
BufferedReader br= new BufferedReader(new InputStreamReader(System.in));
String s = br.readLine();
int i =Integer.parseInt(s);
System.out.println("Enter the second number ");
s = br.readLine();
int j =Integer.parseInt(s);
int k = i + j;
System.out.println("The total is: "+k);
}
catch (IOException e)
{
e.printStackTrace();
} } }
The above code is important since we are using the System.in to take the input from the user and for this we always have to wrap System.in in the InputStreamReader class.
Multi Threading
This is a concept wherein multiple threads within a single process gets executed. When we start a simple program, the default main is a thread and we can also create threads within it.