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