Apr 13, 2012

Data I/O

This section introduces data input and output:
Ø     DataInputStream
Ø     DataOutputStream

What is Data I/O?
Several classes implement the DataInput and DataOutput interfaces. Let's talk about how they work.
The primitive data types, such as int s, may be represented differently on the various platforms that Java code runs on. For example, an int may be represented with the most significant byte first (called Big Endian), as on an IBM mainframe, or with the least significant byte first (called Little Endian), as on an IBM PC. If you wrote out an int in binary form with a C program on one platform and tried to read it in on the other platform, the values would not agree.
That's where DataInput and DataOutput come in. Now you can take a primitive, like an int , and write it out. It is written in a platform-independent form. You can read that int back in on any other Java virtual machine and, regardless of where it was produced, it will be turned back into an int of the proper value.
All the primitives, such as double s, int s, short s, long s, and so forth, can be written in a system platform-independent manner using the methods in DataOutput. Likewise, they can be read using the methods in DataInput.

Unicode Text Format
A String object is written in Unicode Text Format or UTF for short. Strings are composed of two-byte Unicode characters. UTF is a method for compressing the most common Unicode values. If the String contains just ASCII characters, the values between 1 and 127 are written as a single byte. Values 128 - 2047 are written as two bytes. For some uncommon Unicode values, three bytes are used to represent their value. This expansion of some values is much rarer than the compression of ASCII values, so using UTF to represent a String is a net gain.

DataInputStream and DataOutputStream: Example code
Two classes, DataInputStream and DataOutputStream , implement DataInput and DataOutput. Their methods include implementations for readInt() , writeInt() , and the other methods in the interfaces. You wrapper a DataInputStream around an InputStream. When readInt()is called, four bytes are read from the underlying stream and the resulting int is returned. Correspondingly, you wrapper a DataOutputStream around an OutputStream.
The code example below shows a DataOutputStream that uses a FileOutputStream as its underlying stream. The file is opened using a FileInputStream , which has a DataInputStream wrappered around it. The data.dat could be written on an IBM mainframe and read back on an IBM PC.
Here is the example code:
import java.io.*;
class DataInputOutputExample
{
static BufferedReader system_in = new BufferedReader
(new InputStreamReader(System.in));
public static void main(String argv[])
{
// Create it
{
try
{
FileOutputStream fos = new FileOutputStream("data.dat");
DataOutputStream dos = new DataOutputStream(fos);
// Read in three hotels
for (int i = 0; i < 3; i++)
{
Hotel a_hotel = new Hotel();
a_hotel.input(system_in);
a_hotel.write_to_dos(dos);
}
dos.close();
}
catch(IOException e)
{
System.err.println(e);
}
}
// Now read it
{
try
{
FileInputStream fis = new FileInputStream("data.dat");
DataInputStream dis = new DataInputStream(fis);
Hotel a_hotel = new Hotel();
while (a_hotel.read_from_dis(dis))
{
a_hotel.debug_print();
}
dis.close();
}
catch(IOException e)
{
System.err.println(e);
}
}
}
}
class Hotel
{
private String name;
private int rooms;
private String location;
boolean input(BufferedReader in)
{
try
{
System.out.println("Name: ");
name = in.readLine();
System.out.println("Rooms: ");
String temp = in.readLine();
rooms = to_int(temp);
System.out.println("Location: ");
location = in.readLine();
}
catch(IOException e)
{
System.err.println(e);
return false;
}
return true;
}
boolean write_to_dos(DataOutputStream dos)
{
try
{
dos.writeUTF(name);
dos.writeInt(rooms);
dos.writeUTF(location);
}
catch(IOException e)
{
System.err.println(e);
return false;
}
return true;
}
boolean read_from_dis(DataInputStream dis)
{
try
{
name = dis.readUTF();
rooms = dis.readInt();
location = dis.readUTF();
}
catch(EOFException e)
{
return false;
}
catch(IOException e)
{
System.err.println(e);
return false;
}
return true;
}
void debug_print()
{
System.out.println("Name :" + name +
": Rooms : " + rooms + ": at :" + location+ ":");
}
static int to_int(String value)
{
int i = 0;
try
{
i = Integer.parseInt(value);
}
catch(NumberFormatException e)
{}
return i;
}
}

RandomAccessFile: Example code
RandomAccessFile implements both DataInput and DataOutput. You construct RandomAccessFile with a file name. Then you can use both read and write methods, as readInt() and writeInt() , on a RandomAccessFile.
Random access means you can position the next read or write to occur at a particular byte position  within the file. You can obtain the current position with getFilePointer().Later on, you can go back to that same position by passing it to seek().
The example code below shows writing three ints to a file. The file position before the second write is stored in the pointer. After writing the next two ints, the position is restored to that pointer. The readInt() returns the value 15.
Here is the example code:
import java.io.*;
class RandomAccessFileExample
{
public static void main(String argv[])
{
try
{
RandomAccessFile raf =
new RandomAccessFile("random.dat", "rw");
raf.writeInt(12);
long pointer = raf.getFilePointer();
raf.writeInt(15);
raf.writeInt(16);
// Now read back the 2nd one
raf.seek(pointer);
int i = raf.readInt();
System.out.println("Read " + i);
}
catch (IOException e)
{
System.out.println(e);
}
}
}



0 comments :

Post a Comment