Data streams support binary I/O of primitive data type values (boolean,char,byte,short,int,long,float, anddouble) as well as String values. All data streams implement either theDataInputinterface or theDataOutputinterface. This section focuses on the most widely-used implementations of these interfaces,DataInputStreamandDataOutputStream.The
DataStreamsexample demonstrates data streams by writing out a set of data records, and then reading them in again. Each record consists of three values related to an item on an invoice, as shown in the following table:
Order in record Data type Data description Output Method Input Method Sample Value 1 doubleItem price DataOutputStream.writeDoubleDataInputStream.readDouble19.992 intUnit count DataOutputStream.writeIntDataInputStream.readInt123 StringItem description DataOutputStream.writeUTFDataInputStream.readUTF"Java T-Shirt"Let's examine crucial code in
DataStreams. First, the program defines some constants containing the name of the data file and the data that will be written to it:Thenstatic 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" };DataStreamsopens an output stream. Since aDataOutputStreamcan only be created as a wrapper for an existing byte stream object,DataStreamsprovides a buffered file output byte stream.out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dataFile)));DataStreamswrites out the records and closes the output stream.Thefor (int i = 0; i < prices.length; i ++) { out.writeDouble(prices[i]); out.writeInt(units[i]); out.writeUTF(descs[i]); }writeUTFmethod writes outStringvalues in a modified form of UTF-8. This is a variable-width character encoding that only needs a single byte for common Western characters.Now
DataStreamsreads the data back in again. First it must provide an input stream, and variables to hold the input data. LikeDataOutputStream,DataInputStreammust be constructed as a wrapper for a byte stream.Nowin = new DataInputStream(new BufferedInputStream(new FileInputStream(dataFile))); double price; int unit; String desc; double total = 0.0;DataStreamscan read each record in the stream, reporting on the data it encounters.Notice thattry { 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) { }DataStreamsdetects an end-of-file condition by catchingEOFException, instead of testing for an invalid return value. All implementations ofDataInputmethods useEOFExceptioninstead of return values.Also notice that each specialized
writeinDataStreamsis exactly matched by the corresponding specializedread. It is up to the programmer to make sure that output types and input types are matched in this way: The input stream consists of simple binary data, with nothing to indicate the type of individual values, or where they begin in the stream.
DataStreamsuses one very bad programming technique: it uses floating point numbers to represent monetary values. In general, floating point is bad for precise values. It's particularly bad for decimal fractions, because common values (such as0.1) do not have a binary representation.The correct type to use for currency values is
java.math.BigDecimal. Unfortunately,BigDecimalis an object type, so it won't work with data streams. However,BigDecimalwill work with object streams, which are covered in the next section.