view src/ca/randelshofer/DataChunkOutputStream.java @ 34:13d354e1184b

trying to track down very strange bug where a listener and aux listener at the same location hear different things
author Robert McIntyre <rlm@mit.edu>
date Sun, 30 Oct 2011 14:58:01 -0700
parents 4c5fc53778c1
children
line wrap: on
line source
1 /**
2 * @(#)DataChunkOutputStream.java 1.1 2011-01-17
3 *
4 * Copyright (c) 2008-2011 Werner Randelshofer, Immensee, Switzerland.
5 * All rights reserved.
6 *
7 * You may not use, copy or modify this file, except in compliance with the
8 * license agreement you entered into with Werner Randelshofer.
9 * For details see accompanying license terms.
10 */
11 package ca.randelshofer;
13 import java.io.*;
15 /**
16 * This output stream filter supports common data types used inside
17 * of AVI RIFF Data Chunks.
18 *
19 * @author Werner Randelshofer
20 * @version 1.1 2011-01-17 Adds functionality for blocking flush and close.
21 * <br>1.0.1 2010-04-05 Removed unused constants.
22 * <br>1.0 2008-08-11 Created.
23 */
24 public class DataChunkOutputStream extends FilterOutputStream {
26 /**
27 * The number of bytes written to the data output stream so far.
28 * If this counter overflows, it will be wrapped to Integer.MAX_VALUE.
29 */
30 protected long written;
32 /** Whether flush and close request shall be forwarded to underlying stream.*/
33 private boolean forwardFlushAndClose;
35 public DataChunkOutputStream(OutputStream out) {
36 this(out,true);
37 }
38 public DataChunkOutputStream(OutputStream out, boolean forwardFlushAndClose) {
39 super(out);
40 this.forwardFlushAndClose=forwardFlushAndClose;
41 }
43 /**
44 * Writes an chunk type identifier (4 bytes).
45 * @param s A string with a length of 4 characters.
46 */
47 public void writeType(String s) throws IOException {
48 if (s.length() != 4) {
49 throw new IllegalArgumentException("type string must have 4 characters");
50 }
52 try {
53 out.write(s.getBytes("ASCII"), 0, 4);
54 incCount(4);
55 } catch (UnsupportedEncodingException e) {
56 throw new InternalError(e.toString());
57 }
58 }
60 /**
61 * Writes out a <code>byte</code> to the underlying output stream as
62 * a 1-byte value. If no exception is thrown, the counter
63 * <code>written</code> is incremented by <code>1</code>.
64 *
65 * @param v a <code>byte</code> value to be written.
66 * @exception IOException if an I/O error occurs.
67 * @see java.io.FilterOutputStream#out
68 */
69 public final void writeByte(int v) throws IOException {
70 out.write(v);
71 incCount(1);
72 }
74 /**
75 * Writes <code>len</code> bytes from the specified byte array
76 * starting at offset <code>off</code> to the underlying output stream.
77 * If no exception is thrown, the counter <code>written</code> is
78 * incremented by <code>len</code>.
79 *
80 * @param b the data.
81 * @param off the start offset in the data.
82 * @param len the number of bytes to write.
83 * @exception IOException if an I/O error occurs.
84 * @see java.io.FilterOutputStream#out
85 */
86 @Override
87 public synchronized void write(byte b[], int off, int len)
88 throws IOException {
89 out.write(b, off, len);
90 incCount(len);
91 }
93 /**
94 * Writes the specified byte (the low eight bits of the argument
95 * <code>b</code>) to the underlying output stream. If no exception
96 * is thrown, the counter <code>written</code> is incremented by
97 * <code>1</code>.
98 * <p>
99 * Implements the <code>write</code> method of <code>OutputStream</code>.
100 *
101 * @param b the <code>byte</code> to be written.
102 * @exception IOException if an I/O error occurs.
103 * @see java.io.FilterOutputStream#out
104 */
105 @Override
106 public synchronized void write(int b) throws IOException {
107 out.write(b);
108 incCount(1);
109 }
111 /**
112 * Writes an <code>int</code> to the underlying output stream as four
113 * bytes, high byte first. If no exception is thrown, the counter
114 * <code>written</code> is incremented by <code>4</code>.
115 *
116 * @param v an <code>int</code> to be written.
117 * @exception IOException if an I/O error occurs.
118 * @see java.io.FilterOutputStream#out
119 */
120 public void writeInt(int v) throws IOException {
121 out.write((v >>> 0) & 0xff);
122 out.write((v >>> 8) & 0xff);
123 out.write((v >>> 16) & 0xff);
124 out.write((v >>> 24) & 0xff);
125 incCount(4);
126 }
128 /**
129 * Writes an unsigned 32 bit integer value.
130 *
131 * @param v The value
132 * @throws java.io.IOException
133 */
134 public void writeUInt(long v) throws IOException {
135 out.write((int) ((v >>> 0) & 0xff));
136 out.write((int) ((v >>> 8) & 0xff));
137 out.write((int) ((v >>> 16) & 0xff));
138 out.write((int) ((v >>> 24) & 0xff));
139 incCount(4);
140 }
142 /**
143 * Writes a signed 16 bit integer value.
144 *
145 * @param v The value
146 * @throws java.io.IOException
147 */
148 public void writeShort(int v) throws IOException {
149 out.write((int) ((v >>> 0) & 0xff));
150 out.write((int) ((v >> 8) & 0xff));
151 incCount(2);
152 }
154 public void writeLong(long v) throws IOException {
155 out.write((int) (v >>> 0) & 0xff);
156 out.write((int) (v >>> 8) & 0xff);
157 out.write((int) (v >>> 16) & 0xff);
158 out.write((int) (v >>> 24) & 0xff);
159 out.write((int) (v >>> 32) & 0xff);
160 out.write((int) (v >>> 40) & 0xff);
161 out.write((int) (v >>> 48) & 0xff);
162 out.write((int) (v >>> 56) & 0xff);
163 incCount(8);
164 }
166 public void writeUShort(int v) throws IOException {
167 out.write((int) ((v >>> 0) & 0xff));
168 out.write((int) ((v >> 8) & 0xff));
169 incCount(2);
170 }
172 /**
173 * Increases the written counter by the specified value
174 * until it reaches Long.MAX_VALUE.
175 */
176 protected void incCount(int value) {
177 long temp = written + value;
178 if (temp < 0) {
179 temp = Long.MAX_VALUE;
180 }
181 written = temp;
182 }
184 /**
185 * Returns the current value of the counter <code>written</code>,
186 * the number of bytes written to this data output stream so far.
187 * If the counter overflows, it will be wrapped to Integer.MAX_VALUE.
188 *
189 * @return the value of the <code>written</code> field.
190 * @see java.io.DataOutputStream#written
191 */
192 public final long size() {
193 return written;
194 }
196 /**
197 * Sets the value of the counter <code>written</code> to 0.
198 */
199 public void clearCount() {
200 written = 0;
201 }
203 @Override
204 public void close() throws IOException {
205 if (forwardFlushAndClose) {
206 super.close();
207 }
208 }
210 @Override
211 public void flush() throws IOException {
212 if (forwardFlushAndClose) {
213 super.flush();
214 }
215 }
217 }