Data Streams
Data Streams
Introduction
Reading
Data Streams
Introduction
Java
allows the process of input/output to be carried out using streams of input/output data An I/O Stream represents an input source or an output destination. A stream can represent many different kinds of sources and destinations, including disk files, devices, other programs, and memory arrays.
Some streams simply pass on data; others manipulate and transform the data in useful ways. A program uses an input stream to read data from a source, one item at a time.
A program uses an output stream to write data to a destination, one item at time
I/O
Streams are commonly used in Java for communicating over networks, with files, and between applications. Almost all network communication (except UDP communication) is conducted over streams. Hence, a thorough knowledge of I/O streams is critical for network programming in Java.
Byte-level
10001101
10001101
A Data Stream
Provided that the data stream is constructed correctly, what goes in one end comes out the other.
Streams
may be chained together, to provide additional functionality and an easier and more manageable interface. 'a'
111101
Streams
111101
111101
Certainly,
you should not try to read data from an output stream or write data to an input stream. Familiar OutputStream class:
System.out.println();
In
System.in.read() example
import java.io.*; class GradeAverage { public static void main(String args[]) throws IOException { int noCourse = 0; int totalMarks = 0; double gradeAvg; char grade; while (noCourse<10) { System.out.print("Input grade for Course"+(noCourse+1)+" and press <ENTER> "); grade = (char) System.in.read(); switch (grade){ case 'A': totalMarks += 4; break; case 'B': totalMarks += 3; break; case 'C': totalMarks += 2; break; case 'D': totalMarks += 1; break; case 'E': totalMarks += 0; break; } System.in.skip(2); // Newline will be ignored '\n' consists of 2 bytes of data noCourse++; } gradeAvg = (double) totalMarks/noCourse; System.out.println("Your grade average: "+gradeAvg); } }
Run
bytes of data from an in-memory array A ByteArrayInputStream contains an internal buffer that contains bytes that may be read from the stream. An internal counter keeps track of the next byte to be supplied by the read method.
FileInputStream
Reads
bytes of data from a file on the local file system It is meant for reading streams of raw bytes such as image data. For reading streams of characters, consider using FileReader.
PipedInputStream
Reads bytes of data from a thread pipe Reads bytes of data from a string. This class does not properly convert characters into bytes. As of JDK 1.1, the preferred way to create a stream from a string is via the StringReader class. Reads bytes of data from two or more low-level streams, switching from one stream to the next when the end of the stream is reached. Reads bytes of data from the keyboard Surprisingly reading from keyboard in Java is not that straight forward
StringBufferInputStream
SequenceInputStream
System.in
Blocking
stream. Blocking I/O is a term applied to any form of input or output that does not immediately return from an operation. In certain situations, blocking I/O can cause performance problems. This can be alleviated by using data buffering.
input streams, data is communicated sequentially; the first byte in will be the first byte out. Six important low-level output streams: ByteArrayOutputStream
Writes
bytes of data to an array of bytes bytes of data to a file on the local file system
FileOutputStream
Writes
PipedOutputStream
Writes
StringBufferOutputStream
Writes
System.err
Writes
bytes of data to the error stream of the user console, also known as standard error. bytes of data to the user console, also known as standard output.
System.out
Writes
use byte streams to perform input and output of 8-bit bytes. All byte stream classes are inherited from InputStream and OutputStream. To demonstrate how byte streams work, we'll focus on the file I/O byte streams, FileInputStream and FileOutputStream. Byte streams should only be used for the most primitive I/O.
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class CopyBytes { public static void main(String[]args)throws IOException { FileInputStream in = null; FileOutputStream out = null; try { in = new FileInputStream("xanadu.txt"); out = new FileOutputStream("outagain.txt"); int c; while ((c = in.read()) != -1) out.write(c); } finally { if (in != null) in.close(); if (out != null) out.close(); } } }
Simple byte stream input/output - the int variable holds a byte value in its last 8 bits
in CopyCharacters, the int variable holds a character value in its last 16 bits Replace FileInputStream with FileReader Replace FileOutputStream with FileWriter
in = new FileReader("xanadu.txt"); out = new FileWriter("characteroutput.txt");
import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class CopyCharacters { public static void main(String[] args) throws IOException { FileReader inputStream = null; FileWriter outputStream = null; try { inputStream = new FileReader("xanadu.txt"); outputStream = new FileWriter("characteroutput.txt"); int c; while ((c = inputStream.read()) != -1) { outputStream.write(c); } } finally { if (inputStream != null) { inputStream.close(); } if (outputStream != null) { outputStream.close(); } } } }
streams. The character stream uses the byte stream to perform the physical I/O, while the character stream handles translation between characters and bytes. FileReader, for example, uses FileInputStream, while FileWriter uses FileOutputStream.
There
are two general-purpose byte-tocharacter "bridge" streams: InputStreamReader and OutputStreamWriter. Use them to create character streams when there are no prepackaged character stream classes that meet your needs.
Data Streams
Data
streams support binary I/O of primitive data type values (boolean, char, byte, short, int, long, float, and double) as well as String values. All data streams implement either the DataInput interface or the DataOutput interface. This example focuses on the most widely-used implementations of these interfaces, DataInputStream and DataOutputStream.
import java.io.*; public class DataStream { static final String dataFile = "invoicedata"; static final double[] prices = { 19.99, 9.99, 15.99, 3.99, 4.99 }; static final int[] units = { 12, 8, 13, 29, 50 }; static final String[] descs = { "Java T-shirt", "Java Mug", "Duke Juggling Dolls", "Java Pin", "Java Key Chain" }; public static void main(String[] args) throws IOException { DataOutputStream out = null; try { out = new DataOutputStream( new BufferedOutputStream( new FileOutputStream(dataFile)));
for (int i = 0; i < prices.length; i ++) { out.writeDouble(prices[i]); out.writeInt(units[i]); out.writeUTF(descs[i]); } } finally { out.close(); } // Now read back the data from file in = new DataInputStream( new BufferedInputStream( new FileInputStream(dataFile))); double price; int unit; String desc; double total = 0.0;
try { while (true) { price = in.readDouble(); unit = in.readInt(); desc = in.readUTF(); System.out.format("You ordered %d units of %s at $%.2f%n", unit, desc, price); total += unit * price; } } catch (EOFException e) { System.out.println(EOF:+e); }
Filter Streams
The
basic low-level streams have limited flexibility. Filter streams add additional functionality to an existing stream. For example, allowing one to read a line of text instead of reading byte by byte.
Filter
streams can be connected to any other stream (low-level stream or another filter stream). Filter stream classes extend from java.io.FilterInputStream or java.io.FilterOutputStream
Uses I/O buffering for output to improve system performance. Outputs to an internal buffer. Buffer contents are dumped to the output stream when it is full or flushed.
DataOutputStream
Writes primitive data types, such as an int, float, a double, or even a line of text, to an output stream. Offers additional methods for writing lines of text, and other datatypes as text. Provides a convenient way to print primitive datatypes as text using the print() and println() method.
PrintStream
Example:
FileOutputStream fout; DataOutputStream dos; fout = new FileOutputStream("out"); dos = new DataOutputStream(fout); dos.writeInt(1024); dos.writeFloat(43.235);
DataOutput Stream FileOutput Stream
1024
int
bytes
File
Uses I/O buffering for input to improve system performance. Tries to reduce the number of times an application blocks for input by reading bytes in batches into a buffer.
DataInputStream
Reads primitive data types, such as an int, float, a double, or even a line of text, from an input stream.
Example:
FileInputStream fin; DataInputStream dis; fin = new FileInputStream(data.dat"); dis = new DataInputStream(fin); int intData = dis.readInt(); float floatData = dis.readFloat(); System.out.println("Int data: "+intData); System.out.println("Float data: "+floatData);
DataInput Stream FileInput Stream
1024
int
bytes
File
Object Stream
Just
as data streams support I/O of primitive data types, object streams support I/O of objects. Most, but not all, standard classes support serialization of their objects. Those that do implement the marker interface Serializable. The object stream classes are ObjectInputStream and ObjectOutputStream. These classes implement ObjectInput and ObjectOutput, which are subinterfaces of DataInput and DataOutput.
Object Stream
So
an object stream can contain a mixture of primitive and object values. The ObjectStreams example illustrates this. ObjectStreams creates the same application as DataStreams, with a couple of changes.
First, prices are now BigDecimalobjects, to better represent fractional values. Second, a Calendar object is written to the data file, indicating an invoice date.
Run
writeObject and readObject methods are simple to use, but they contain some very sophisticated object management logic. This isn't important for a class like Calendar, which just encapsulates primitive values. But many objects contain references to other objects. If readObject is to reconstitute an object from a stream, it has to be able to reconstitute all of the objects the original object referred to.
writeObject
is invoked to write a single object named a. This object contains references to objects b and c, while b contains references to d and e. Invoking writeobject(a) writes not just a, but all the objects necessary to reconstitute a, so the other four objects in this web are written also. When a is read back by readObject, the other four objects are read back as well, and all the original object references are preserved.