rlm@9: /* rlm@9: * @(#)SeekableByteArrayOutputStream.java 1.0 2010-12-27 rlm@9: * rlm@9: * Copyright © 2010 Werner Randelshofer, Immensee, Switzerland. rlm@9: * All rights reserved. rlm@9: * rlm@9: * You may not use, copy or modify this file, except in compliance with the rlm@9: * license agreement you entered into with Werner Randelshofer. rlm@9: * For details see accompanying license terms. rlm@9: */ rlm@9: rlm@9: package com.aurellem.capture.audio; rlm@9: rlm@9: import java.io.ByteArrayOutputStream; rlm@9: import java.io.IOException; rlm@9: import java.io.OutputStream; rlm@9: import java.util.Arrays; rlm@9: import static java.lang.Math.*; rlm@9: /** rlm@9: * {@code SeekableByteArrayOutputStream}. rlm@9: * rlm@9: * @author Werner Randelshofer rlm@9: * @version 1.0 2010-12-27 Created. rlm@9: */ rlm@9: public class SeekableByteArrayOutputStream extends ByteArrayOutputStream { rlm@9: rlm@9: /** rlm@9: * The current stream position. rlm@9: */ rlm@9: private int pos; rlm@9: rlm@9: /** rlm@9: * Creates a new byte array output stream. The buffer capacity is rlm@9: * initially 32 bytes, though its size increases if necessary. rlm@9: */ rlm@9: public SeekableByteArrayOutputStream() { rlm@9: this(32); rlm@9: } rlm@9: rlm@9: /** rlm@9: * Creates a new byte array output stream, with a buffer capacity of rlm@9: * the specified size, in bytes. rlm@9: * rlm@9: * @param size the initial size. rlm@9: * @exception IllegalArgumentException if size is negative. rlm@9: */ rlm@9: public SeekableByteArrayOutputStream(int size) { rlm@9: if (size < 0) { rlm@9: throw new IllegalArgumentException("Negative initial size: " rlm@9: + size); rlm@9: } rlm@9: buf = new byte[size]; rlm@9: } rlm@9: rlm@9: /** rlm@9: * Writes the specified byte to this byte array output stream. rlm@9: * rlm@9: * @param b the byte to be written. rlm@9: */ rlm@9: @Override rlm@9: public synchronized void write(int b) { rlm@9: int newcount = max(pos + 1, count); rlm@9: if (newcount > buf.length) { rlm@9: buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount)); rlm@9: } rlm@9: buf[pos++] = (byte)b; rlm@9: count = newcount; rlm@9: } rlm@9: rlm@9: /** rlm@9: * Writes len bytes from the specified byte array rlm@9: * starting at offset off to this byte array output stream. rlm@9: * rlm@9: * @param b the data. rlm@9: * @param off the start offset in the data. rlm@9: * @param len the number of bytes to write. rlm@9: */ rlm@9: @Override rlm@9: public synchronized void write(byte b[], int off, int len) { rlm@9: if ((off < 0) || (off > b.length) || (len < 0) || rlm@9: ((off + len) > b.length) || ((off + len) < 0)) { rlm@9: throw new IndexOutOfBoundsException(); rlm@9: } else if (len == 0) { rlm@9: return; rlm@9: } rlm@9: int newcount = max(pos+len,count); rlm@9: if (newcount > buf.length) { rlm@9: buf = Arrays.copyOf(buf, Math.max(buf.length << 1, newcount)); rlm@9: } rlm@9: System.arraycopy(b, off, buf, pos, len); rlm@9: pos+=len; rlm@9: count = newcount; rlm@9: } rlm@9: rlm@9: /** rlm@9: * Resets the count field of this byte array output rlm@9: * stream to zero, so that all currently accumulated output in the rlm@9: * output stream is discarded. The output stream can be used again, rlm@9: * reusing the already allocated buffer space. rlm@9: * rlm@9: * @see java.io.ByteArrayInputStream#count rlm@9: */ rlm@9: @Override rlm@9: public synchronized void reset() { rlm@9: count = 0; rlm@9: pos=0; rlm@9: } rlm@9: rlm@9: /** rlm@9: * Sets the current stream position to the desired location. The rlm@9: * next read will occur at this location. The bit offset is set rlm@9: * to 0. rlm@9: * rlm@9: *

An IndexOutOfBoundsException will be thrown if rlm@9: * pos is smaller than the flushed position (as rlm@9: * returned by getflushedPosition). rlm@9: * rlm@9: *

It is legal to seek past the end of the file; an rlm@9: * EOFException will be thrown only if a read is rlm@9: * performed. rlm@9: * rlm@9: * @param pos a long containing the desired file rlm@9: * pointer position. rlm@9: * rlm@9: * @exception IndexOutOfBoundsException if pos is smaller rlm@9: * than the flushed position. rlm@9: * @exception IOException if any other I/O error occurs. rlm@9: */ rlm@9: public void seek(long pos) throws IOException { rlm@9: this.pos = (int)pos; rlm@9: } rlm@9: rlm@9: /** rlm@9: * Returns the current byte position of the stream. The next write rlm@9: * will take place starting at this offset. rlm@9: * rlm@9: * @return a long containing the position of the stream. rlm@9: * rlm@9: * @exception IOException if an I/O error occurs. rlm@9: */ rlm@9: public long getStreamPosition() throws IOException { rlm@9: return pos; rlm@9: } rlm@9: rlm@9: /** Writes the contents of the byte array into the specified output rlm@9: * stream. rlm@9: * @param out rlm@9: */ rlm@9: public void toOutputStream(OutputStream out) throws IOException { rlm@9: out.write(buf, 0, count); rlm@9: } rlm@9: rlm@9: }