View Javadoc
1   //******************************************************************************
2   //
3   // File:    DataOutputStream.java
4   // Package: edu.rit.io
5   // Unit:    Class edu.rit.io.DataOutputStream
6   //
7   // This Java source file is copyright (C) 2009 by Alan Kaminsky. All rights
8   // reserved. For further information, contact the author, Alan Kaminsky, at
9   // ark@cs.rit.edu.
10  //
11  // This Java source file is part of the Parallel Java Library ("PJ"). PJ is free
12  // software; you can redistribute it and/or modify it under the terms of the GNU
13  // General Public License as published by the Free Software Foundation; either
14  // version 3 of the License, or (at your option) any later version.
15  //
16  // PJ is distributed in the hope that it will be useful, but WITHOUT ANY
17  // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18  // A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19  //
20  // Linking this library statically or dynamically with other modules is making a
21  // combined work based on this library. Thus, the terms and conditions of the GNU
22  // General Public License cover the whole combination.
23  //
24  // As a special exception, the copyright holders of this library give you
25  // permission to link this library with independent modules to produce an
26  // executable, regardless of the license terms of these independent modules, and
27  // to copy and distribute the resulting executable under terms of your choice,
28  // provided that you also meet, for each linked independent module, the terms
29  // and conditions of the license of that module. An independent module is a module
30  // which is not derived from or based on this library. If you modify this library,
31  // you may extend this exception to your version of the library, but you are not
32  // obligated to do so. If you do not wish to do so, delete this exception
33  // statement from your version.
34  //
35  // A copy of the GNU General Public License is provided in the file gpl.txt. You
36  // may also obtain a copy of the GNU General Public License on the World Wide
37  // Web at http://www.gnu.org/licenses/gpl.html.
38  //
39  //******************************************************************************
40  package edu.rit.io;
41  
42  import java.io.FilterOutputStream;
43  import java.io.IOException;
44  import java.io.OutputStream;
45  
46  /**
47   * Class DataOutputStream provides an output stream that writes primitive data
48   * types and strings in binary form. It behaves similarly to class
49   * java.io.DataOutputStream, except the methods for writing types byte, short,
50   * char, int, long, and String are implemented differently. These methods write
51   * an integer value using a variable number of bytes, as described below. This
52   * can save space in the file if small integer values are written more
53   * frequently than large integer values. The resulting byte stream can be read
54   * using class {@linkplain DataInputStream}.
55   * <p>
56   * Note that class DataOutputStream does <I>not</I> implement interface
57   * java.io.DataOutput, because the methods do not obey the contract specified in
58   * that interface.
59   *
60   * @author Alan Kaminsky
61   * @version 18-Dec-2009
62   */
63  public class DataOutputStream
64          extends FilterOutputStream {
65  
66  // Exported constructors.
67  
68      /**
69       * Construct a new data output stream.
70       *
71       * @param out Underlying output stream.
72       */
73      public DataOutputStream(OutputStream out) {
74          super(out);
75      }
76  
77  // Exported operations.
78  
79      /**
80       * Write the given Boolean value to this data output stream. One byte is
81       * written, either 0 (if <code>v</code> is false) or 1 (if <code>v</code> is true).
82       *
83       * @param v Boolean value.
84       * @throws java.io.IOException         Thrown if an I/O error occurred.
85       * @throws java.io.IOException if any.
86       */
87      public void writeBoolean(boolean v)
88              throws IOException {
89          out.write(v ? 1 : 0);
90      }
91  
92      /**
93       * Write the given integer value to this data output stream. This method can
94       * be used to write values of type byte, short, char, or int. From one to
95       * five bytes are written, in big-endian order, as follows:
96       * <UL>
97       *
98       * <LI>
99       * If &minus;64 &le; <code>v</code> &le; 63, then one byte is written,
100      * containing 0 (1 bit) followed by <code>v</code> (7 bits).
101      *
102      * <LI>
103      * Else if &minus;8192 &le; <code>v</code> &le; 8191, then two bytes are
104      * written, containing 10 (2 bits) followed by <code>v</code> (14 bits).
105      *
106      * <LI>
107      * Else if &minus;1048576 &le; <code>v</code> &le; 1048575, then three bytes are
108      * written, containing 110 (3 bits) followed by <code>v</code> (21 bits).
109      *
110      * <LI>
111      * Else if &minus;134217728 &le; <code>v</code> &le; 134217727, then four bytes
112      * are written, containing 1110 (4 bits) followed by <code>v</code> (28 bits).
113      *
114      * <LI>
115      * Else five bytes are written, containing 1111 (4 bits) followed by
116      * <code>v</code> (sign-extended to 36 bits).
117      * </UL>
118      *
119      * @param v Integer value.
120      * @throws java.io.IOException         Thrown if an I/O error occurred.
121      * @throws java.io.IOException if any.
122      */
123     public void writeInt(int v)
124             throws IOException {
125         if (-64 <= v && v <= 63) {
126             out.write(v & 0x7F);
127         } else if (-8192 <= v && v <= 8191) {
128             out.write(((v >> 8) & 0x3F) | 0x80);
129             out.write(v);
130         } else if (-1048576 <= v && v <= 1048575) {
131             out.write(((v >> 16) & 0x1F) | 0xC0);
132             out.write(v >> 8);
133             out.write(v);
134         } else if (-134217728 <= v && v <= 134217727) {
135             out.write(((v >> 24) & 0x0F) | 0xE0);
136             out.write(v >> 16);
137             out.write(v >> 8);
138             out.write(v);
139         } else {
140             out.write(((v >> 32) & 0x0F) | 0xF0);
141             out.write(v >> 24);
142             out.write(v >> 16);
143             out.write(v >> 8);
144             out.write(v);
145         }
146     }
147 
148     /**
149      * Write the given unsigned integer value to this data output stream. This
150      * method can be used to write values of type byte, short, char, or int.
151      * From one to five bytes are written, in big-endian order, as follows:
152      * <UL>
153      *
154      * <LI>
155      * If 0 &le; <code>v</code> &le; 127, then one byte is written, containing 0 (1
156      * bit) followed by <code>v</code> (7 bits).
157      *
158      * <LI>
159      * Else if 128 &le; <code>v</code> &le; 16383, then two bytes are written,
160      * containing 10 (2 bits) followed by <code>v</code> (14 bits).
161      *
162      * <LI>
163      * Else if 16384 &le; <code>v</code> &le; 2097151, then three bytes are written,
164      * containing 110 (3 bits) followed by <code>v</code> (21 bits).
165      *
166      * <LI>
167      * Else if 2097152 &le; <code>v</code> &le; 268435455, then four bytes are
168      * written, containing 1110 (4 bits) followed by <code>v</code> (28 bits).
169      *
170      * <LI>
171      * Else five bytes are written, containing 1111 (4 bits) followed by
172      * <code>v</code> (zero-extended to 36 bits).
173      * </UL>
174      *
175      * @param v Integer value.
176      * @throws java.io.IOException         Thrown if an I/O error occurred.
177      * @throws java.io.IOException if any.
178      */
179     public void writeUnsignedInt(int v)
180             throws IOException {
181         if (0 <= v && v <= 127) {
182             out.write(v);
183         } else if (128 <= v && v <= 16383) {
184             out.write((v >> 8) | 0x80);
185             out.write(v);
186         } else if (16384 <= v && v <= 2097151) {
187             out.write((v >> 16) | 0xC0);
188             out.write(v >> 8);
189             out.write(v);
190         } else if (2097152 <= v && v <= 268435455) {
191             out.write((v >> 24) | 0xE0);
192             out.write(v >> 16);
193             out.write(v >> 8);
194             out.write(v);
195         } else {
196             out.write(0xF0);
197             out.write(v >> 24);
198             out.write(v >> 16);
199             out.write(v >> 8);
200             out.write(v);
201         }
202     }
203 
204     /**
205      * Write the given long value to this data output stream. From one to nine
206      * bytes are written, in big-endian order, as follows:
207      * <UL>
208      *
209      * <LI>
210      * If &minus;64 &le; <code>v</code> &le; 63, then one byte is written,
211      * containing 0 (1 bit) followed by <code>v</code> (7 bits).
212      *
213      * <LI>
214      * Else if &minus;8192 &le; <code>v</code> &le; 8191, then two bytes are
215      * written, containing 10 (2 bits) followed by <code>v</code> (14 bits).
216      *
217      * <LI>
218      * Else if &minus;1048576 &le; <code>v</code> &le; 1048575, then three bytes are
219      * written, containing 110 (3 bits) followed by <code>v</code> (21 bits).
220      *
221      * <LI>
222      * Else if &minus;134217728 &le; <code>v</code> &le; 134217727, then four bytes
223      * are written, containing 1110 (4 bits) followed by <code>v</code> (28 bits).
224      *
225      * <LI>
226      * Else if &minus;17179869184 &le; <code>v</code> &le; 17179869183, then five
227      * bytes are written, containing 11110 (5 bits) followed by <code>v</code> (35
228      * bits).
229      *
230      * <LI>
231      * Else if &minus;2199023255552 &le; <code>v</code> &le; 2199023255551, then six
232      * bytes are written, containing 111110 (6 bits) followed by <code>v</code> (42
233      * bits).
234      *
235      * <LI>
236      * Else if &minus;281474976710656 &le; <code>v</code> &le; 281474976710655, then
237      * seven bytes are written, containing 1111110 (7 bits) followed by
238      * <code>v</code> (49 bits).
239      *
240      * <LI>
241      * Else if &minus;36028797018963968 &le; <code>v</code> &le; 36028797018963967,
242      * then eight bytes are written, containing 11111110 (8 bits) followed by
243      * <code>v</code> (56 bits).
244      *
245      * <LI>
246      * Else nine bytes are written, containing 11111111 (8 bits) followed by
247      * <code>v</code> (64 bits).
248      * </UL>
249      *
250      * @param v Integer value.
251      * @throws java.io.IOException         Thrown if an I/O error occurred.
252      * @throws java.io.IOException if any.
253      */
254     public void writeLong(long v)
255             throws IOException {
256         if (-64L <= v && v <= 63L) {
257             out.write((int) (v) & 0x7F);
258         } else if (-8192L <= v && v <= 8191L) {
259             out.write(((int) (v >> 8L) & 0x3F) | 0x80);
260             out.write((int) (v));
261         } else if (-1048576L <= v && v <= 1048575L) {
262             out.write(((int) (v >> 16L) & 0x1F) | 0xC0);
263             out.write((int) (v >> 8L));
264             out.write((int) (v));
265         } else if (-134217728L <= v && v <= 134217727L) {
266             out.write(((int) (v >> 24L) & 0x0F) | 0xE0);
267             out.write((int) (v >> 16L));
268             out.write((int) (v >> 8L));
269             out.write((int) (v));
270         } else if (-17179869184L <= v && v <= 17179869183L) {
271             out.write(((int) (v >> 32L) & 0x07) | 0xF0);
272             out.write((int) (v >> 24L));
273             out.write((int) (v >> 16L));
274             out.write((int) (v >> 8L));
275             out.write((int) (v));
276         } else if (-2199023255552L <= v && v <= 2199023255551L) {
277             out.write(((int) (v >> 40L) & 0x03) | 0xF8);
278             out.write((int) (v >> 32L));
279             out.write((int) (v >> 24L));
280             out.write((int) (v >> 16L));
281             out.write((int) (v >> 8L));
282             out.write((int) (v));
283         } else if (-281474976710656L <= v && v <= 281474976710656L) {
284             out.write(((int) (v >> 48L) & 0x01) | 0xFC);
285             out.write((int) (v >> 40L));
286             out.write((int) (v >> 32L));
287             out.write((int) (v >> 24L));
288             out.write((int) (v >> 16L));
289             out.write((int) (v >> 8L));
290             out.write((int) (v));
291         } else if (-36028797018963968L <= v && v <= 36028797018963968L) {
292             out.write(0xFE);
293             out.write((int) (v >> 48L));
294             out.write((int) (v >> 40L));
295             out.write((int) (v >> 32L));
296             out.write((int) (v >> 24L));
297             out.write((int) (v >> 16L));
298             out.write((int) (v >> 8L));
299             out.write((int) (v));
300         } else {
301             out.write(0xFF);
302             out.write((int) (v >> 56L));
303             out.write((int) (v >> 48L));
304             out.write((int) (v >> 40L));
305             out.write((int) (v >> 32L));
306             out.write((int) (v >> 24L));
307             out.write((int) (v >> 16L));
308             out.write((int) (v >> 8L));
309             out.write((int) (v));
310         }
311     }
312 
313     /**
314      * Write the given unsigned long value to this data output stream. From one
315      * to nine bytes are written, in big-endian order, as follows:
316      * <UL>
317      *
318      * <LI>
319      * If 0 &le; <code>v</code> &le; 127, then one byte is written, containing 0 (1
320      * bit) followed by <code>v</code> (7 bits).
321      *
322      * <LI>
323      * Else if 128 &le; <code>v</code> &le; 16383, then two bytes are written,
324      * containing 10 (2 bits) followed by <code>v</code> (14 bits).
325      *
326      * <LI>
327      * Else if 16384 &le; <code>v</code> &le; 2097151, then three bytes are written,
328      * containing 110 (3 bits) followed by <code>v</code> (21 bits).
329      *
330      * <LI>
331      * Else if 2097152 &le; <code>v</code> &le; 268435455, then four bytes are
332      * written, containing 1110 (4 bits) followed by <code>v</code> (28 bits).
333      *
334      * <LI>
335      * Else if 268435456 &le; <code>v</code> &le; 34359738367, then five bytes are
336      * written, containing 11110 (5 bits) followed by <code>v</code> (35 bits).
337      *
338      * <LI>
339      * Else if 34359738368 &le; <code>v</code> &le; 4398046511103, then six bytes
340      * are written, containing 111110 (6 bits) followed by <code>v</code> (42 bits).
341      *
342      * <LI>
343      * Else if 4398046511104 &le; <code>v</code> &le; 562949953421311, then seven
344      * bytes are written, containing 1111110 (7 bits) followed by <code>v</code> (49
345      * bits).
346      *
347      * <LI>
348      * Else if 562949953421312 &le; <code>v</code> &le; 72057594037927935, then
349      * eight bytes are written, containing 11111110 (8 bits) followed by
350      * <code>v</code> (56 bits).
351      *
352      * <LI>
353      * Else nine bytes are written, containing 11111111 (8 bits) followed by
354      * <code>v</code> (64 bits).
355      * </UL>
356      *
357      * @param v Integer value.
358      * @throws java.io.IOException         Thrown if an I/O error occurred.
359      * @throws java.io.IOException if any.
360      */
361     public void writeUnsignedLong(long v)
362             throws IOException {
363         if (0L <= v && v <= 127L) {
364             out.write((int) (v));
365         } else if (128L <= v && v <= 16383L) {
366             out.write((int) (v >> 8L) | 0x80);
367             out.write((int) (v));
368         } else if (16384L <= v && v <= 2097151L) {
369             out.write((int) (v >> 16L) | 0xC0);
370             out.write((int) (v >> 8L));
371             out.write((int) (v));
372         } else if (2097152L <= v && v <= 268435455L) {
373             out.write((int) (v >> 24L) | 0xE0);
374             out.write((int) (v >> 16L));
375             out.write((int) (v >> 8L));
376             out.write((int) (v));
377         } else if (268435456L <= v && v <= 34359738367L) {
378             out.write((int) (v >> 32L) | 0xF0);
379             out.write((int) (v >> 24L));
380             out.write((int) (v >> 16L));
381             out.write((int) (v >> 8L));
382             out.write((int) (v));
383         } else if (34359738368L <= v && v <= 4398046511103L) {
384             out.write((int) (v >> 40L) | 0xF8);
385             out.write((int) (v >> 32L));
386             out.write((int) (v >> 24L));
387             out.write((int) (v >> 16L));
388             out.write((int) (v >> 8L));
389             out.write((int) (v));
390         } else if (4398046511104L <= v && v <= 562949953421311L) {
391             out.write((int) (v >> 48L) | 0xFC);
392             out.write((int) (v >> 40L));
393             out.write((int) (v >> 32L));
394             out.write((int) (v >> 24L));
395             out.write((int) (v >> 16L));
396             out.write((int) (v >> 8L));
397             out.write((int) (v));
398         } else if (562949953421312L <= v && v <= 72057594037927935L) {
399             out.write(0xFE);
400             out.write((int) (v >> 48L));
401             out.write((int) (v >> 40L));
402             out.write((int) (v >> 32L));
403             out.write((int) (v >> 24L));
404             out.write((int) (v >> 16L));
405             out.write((int) (v >> 8L));
406             out.write((int) (v));
407         } else {
408             out.write(0xFF);
409             out.write((int) (v >> 56L));
410             out.write((int) (v >> 48L));
411             out.write((int) (v >> 40L));
412             out.write((int) (v >> 32L));
413             out.write((int) (v >> 24L));
414             out.write((int) (v >> 16L));
415             out.write((int) (v >> 8L));
416             out.write((int) (v));
417         }
418     }
419 
420     /**
421      * Write the given float value to this data output stream. Four bytes are
422      * written in big-endian order containing
423      * <code>Float.floatToRawIntBits(v)</code>.
424      *
425      * @param v Float value.
426      * @throws java.io.IOException         Thrown if an I/O error occurred.
427      * @throws java.io.IOException if any.
428      */
429     public void writeFloat(float v)
430             throws IOException {
431         int x = Float.floatToRawIntBits(v);
432         out.write(x >> 24);
433         out.write(x >> 16);
434         out.write(x >> 8);
435         out.write(x);
436     }
437 
438     /**
439      * Write the given double value to this data output stream. Eight bytes are
440      * written in big-endian order containing
441      * <code>Double.doubleToRawLongBits(v)</code>.
442      *
443      * @param v Double value.
444      * @throws java.io.IOException         Thrown if an I/O error occurred.
445      * @throws java.io.IOException if any.
446      */
447     public void writeDouble(double v)
448             throws IOException {
449         long x = Double.doubleToRawLongBits(v);
450         out.write((int) (x >> 56L));
451         out.write((int) (x >> 48L));
452         out.write((int) (x >> 40L));
453         out.write((int) (x >> 32L));
454         out.write((int) (x >> 24L));
455         out.write((int) (x >> 16L));
456         out.write((int) (x >> 8L));
457         out.write((int) (x));
458     }
459 
460     /**
461      * Write the given string value to this data output stream. The length of
462      * the string is written using <code>writeUnsignedInt()</code>, then each
463      * character of the string is written using <code>writeUnsignedInt()</code>.
464      *
465      * @param v String value.
466      * @throws java.io.IOException         Thrown if an I/O error occurred.
467      * @throws java.io.IOException if any.
468      */
469     public void writeString(String v)
470             throws IOException {
471         int n = v.length();
472         writeUnsignedInt(n);
473         for (int i = 0; i < n; ++i) {
474             writeUnsignedInt(v.charAt(i));
475         }
476     }
477 
478 }