View Javadoc

    1   /*
    2    * $Id: FastByteArrayOutputStream.java 471756 2006-11-06 15:01:43Z husted $
    3    *
    4    * Licensed to the Apache Software Foundation (ASF) under one
    5    * or more contributor license agreements.  See the NOTICE file
    6    * distributed with this work for additional information
    7    * regarding copyright ownership.  The ASF licenses this file
    8    * to you under the Apache License, Version 2.0 (the
    9    * "License"); you may not use this file except in compliance
    10   * with the License.  You may obtain a copy of the License at
    11   *
    12   *  http://www.apache.org/licenses/LICENSE-2.0
    13   *
    14   * Unless required by applicable law or agreed to in writing,
    15   * software distributed under the License is distributed on an
    16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    17   * KIND, either express or implied.  See the License for the
    18   * specific language governing permissions and limitations
    19   * under the License.
    20   */
    21  package org.apache.struts2.util;
    22
    23  import java.io.IOException;
    24  import java.io.OutputStream;
    25  import java.io.RandomAccessFile;
    26  import java.io.Writer;
    27  import java.util.Iterator;
    28  import java.util.LinkedList;
    29
    30
    31  /***
    32   * A speedy implementation of ByteArrayOutputStream. It's not synchronized, and it
    33   * does not copy buffers when it's expanded. There's also no copying of the internal buffer
    34   * if it's contents is extracted with the writeTo(stream) method.
    35   *
    36   */
    37  public class FastByteArrayOutputStream extends OutputStream {
    38
    39      // Static --------------------------------------------------------
    40      private static final int DEFAULT_BLOCK_SIZE = 8192;
    41
    42
    43      private LinkedList buffers;
    44
    45      // Attributes ----------------------------------------------------
    46      // internal buffer
    47      private byte[] buffer;
    48
    49      // is the stream closed?
    50      private boolean closed;
    51      private int blockSize;
    52      private int index;
    53      private int size;
    54
    55
    56      // Constructors --------------------------------------------------
    57      public FastByteArrayOutputStream() {
    58          this(DEFAULT_BLOCK_SIZE);
    59      }
    60
    61      public FastByteArrayOutputStream(int aSize) {
    62          blockSize = aSize;
    63          buffer = new byte[blockSize];
    64      }
    65
    66
    67      public int getSize() {
    68          return size + index;
    69      }
    70
    71      public void close() {
    72          closed = true;
    73      }
    74
    75      public byte[] toByteArray() {
    76          byte[] data = new byte[getSize()];
    77
    78          // Check if we have a list of buffers
    79          int pos = 0;
    80
    81          if (buffers != null) {
    82              Iterator iter = buffers.iterator();
    83
    84              while (iter.hasNext()) {
    85                  byte[] bytes = (byte[]) iter.next();
    86                  System.arraycopy(bytes, 0, data, pos, blockSize);
    87                  pos += blockSize;
    88              }
    89          }
    90
    91          // write the internal buffer directly
    92          System.arraycopy(buffer, 0, data, pos, index);
    93
    94          return data;
    95      }
    96
    97      public String toString() {
    98          return new String(toByteArray());
    99      }
    100
    101     // OutputStream overrides ----------------------------------------
    102     public void write(int datum) throws IOException {
    103         if (closed) {
    104             throw new IOException("Stream closed");
    105         } else {
    106             if (index == blockSize) {
    107                 addBuffer();
    108             }
    109
    110             // store the byte
    111             buffer[index++] = (byte) datum;
    112         }
    113     }
    114
    115     public void write(byte[] data, int offset, int length) throws IOException {
    116         if (data == null) {
    117             throw new NullPointerException();
    118         } else if ((offset < 0) || ((offset + length) > data.length) || (length < 0)) {
    119             throw new IndexOutOfBoundsException();
    120         } else if (closed) {
    121             throw new IOException("Stream closed");
    122         } else {
    123             if ((index + length) > blockSize) {
    124                 int copyLength;
    125
    126                 do {
    127                     if (index == blockSize) {
    128                         addBuffer();
    129                     }
    130
    131                     copyLength = blockSize - index;
    132
    133                     if (length < copyLength) {
    134                         copyLength = length;
    135                     }
    136
    137                     System.arraycopy(data, offset, buffer, index, copyLength);
    138                     offset += copyLength;
    139                     index += copyLength;
    140                     length -= copyLength;
    141                 } while (length > 0);
    142             } else {
    143                 // Copy in the subarray
    144                 System.arraycopy(data, offset, buffer, index, length);
    145                 index += length;
    146             }
    147         }
    148     }
    149
    150     // Public
    151     public void writeTo(OutputStream out) throws IOException {
    152         // Check if we have a list of buffers
    153         if (buffers != null) {
    154             Iterator iter = buffers.iterator();
    155
    156             while (iter.hasNext()) {
    157                 byte[] bytes = (byte[]) iter.next();
    158                 out.write(bytes, 0, blockSize);
    159             }
    160         }
    161
    162         // write the internal buffer directly
    163         out.write(buffer, 0, index);
    164     }
    165
    166     public void writeTo(RandomAccessFile out) throws IOException {
    167         // Check if we have a list of buffers
    168         if (buffers != null) {
    169             Iterator iter = buffers.iterator();
    170
    171             while (iter.hasNext()) {
    172                 byte[] bytes = (byte[]) iter.next();
    173                 out.write(bytes, 0, blockSize);
    174             }
    175         }
    176
    177         // write the internal buffer directly
    178         out.write(buffer, 0, index);
    179     }
    180
    181     public void writeTo(Writer out, String encoding) throws IOException {
    182         // Check if we have a list of buffers
    183         if (buffers != null) {
    184             Iterator iter = buffers.iterator();
    185
    186             while (iter.hasNext()) {
    187                 byte[] bytes = (byte[]) iter.next();
    188
    189                 if (encoding != null) {
    190                     out.write(new String(bytes, encoding));
    191                 } else {
    192                     out.write(new String(bytes));
    193                 }
    194             }
    195         }
    196
    197         // write the internal buffer directly
    198         if (encoding != null) {
    199             out.write(new String(buffer, 0, index, encoding));
    200         } else {
    201             out.write(new String(buffer, 0, index));
    202         }
    203     }
    204
    205     /***
    206      * Create a new buffer and store the
    207      * current one in linked list
    208      */
    209     protected void addBuffer() {
    210         if (buffers == null) {
    211             buffers = new LinkedList();
    212         }
    213
    214         buffers.addLast(buffer);
    215
    216         buffer = new byte[blockSize];
    217         size += index;
    218         index = 0;
    219     }
    220 }