Home | History | Annotate | Download | only in utils
      1 /*******************************************************************************
      2  * Copyright 2011 See AUTHORS file.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *   http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  ******************************************************************************/
     16 
     17 package com.badlogic.gdx.utils;
     18 
     19 import java.io.ByteArrayOutputStream;
     20 import java.io.Closeable;
     21 import java.io.IOException;
     22 import java.io.InputStream;
     23 import java.io.InputStreamReader;
     24 import java.io.OutputStream;
     25 import java.io.StringWriter;
     26 import java.nio.ByteBuffer;
     27 
     28 /** Provides utility methods to copy streams. */
     29 public final class StreamUtils {
     30 	public static final int DEFAULT_BUFFER_SIZE = 4096;
     31 	public static final byte[] EMPTY_BYTES = new byte[0];
     32 
     33 	/** Allocates a {@value #DEFAULT_BUFFER_SIZE} byte[] for use as a temporary buffer and calls
     34 	 * {@link #copyStream(InputStream, OutputStream, byte[])}. */
     35 	public static void copyStream (InputStream input, OutputStream output) throws IOException {
     36 		copyStream(input, output, new byte[DEFAULT_BUFFER_SIZE]);
     37 	}
     38 
     39 	/** Allocates a byte[] of the specified size for use as a temporary buffer and calls
     40 	 * {@link #copyStream(InputStream, OutputStream, byte[])}. */
     41 	public static void copyStream (InputStream input, OutputStream output, int bufferSize) throws IOException {
     42 		copyStream(input, output, new byte[bufferSize]);
     43 	}
     44 
     45 	/** Copy the data from an {@link InputStream} to an {@link OutputStream}, using the specified byte[] as a temporary buffer. The
     46 	 * stream is not closed. */
     47 	public static void copyStream (InputStream input, OutputStream output, byte[] buffer) throws IOException {
     48 		int bytesRead;
     49 		while ((bytesRead = input.read(buffer)) != -1) {
     50 			output.write(buffer, 0, bytesRead);
     51 		}
     52 	}
     53 
     54 	/** Allocates a {@value #DEFAULT_BUFFER_SIZE} byte[] for use as a temporary buffer and calls
     55 	 * {@link #copyStream(InputStream, OutputStream, byte[])}. */
     56 	public static void copyStream (InputStream input, ByteBuffer output) throws IOException {
     57 		copyStream(input, output, new byte[DEFAULT_BUFFER_SIZE]);
     58 	}
     59 
     60 	/** Allocates a byte[] of the specified size for use as a temporary buffer and calls
     61 	 * {@link #copyStream(InputStream, ByteBuffer, byte[])}. */
     62 	public static void copyStream (InputStream input, ByteBuffer output, int bufferSize) throws IOException {
     63 		copyStream(input, output, new byte[bufferSize]);
     64 	}
     65 
     66 	/** Copy the data from an {@link InputStream} to a {@link ByteBuffer}, using the specified byte[] as a temporary buffer. The
     67 	 * buffer's limit is increased by the number of bytes copied, the position is left unchanged. The stream is not closed.
     68 	 * @param output Must be a direct Buffer with native byte order and the buffer MUST be large enough to hold all the bytes in
     69 	 *           the stream. No error checking is performed.
     70 	 * @return the number of bytes copied. */
     71 	public static int copyStream (InputStream input, ByteBuffer output, byte[] buffer) throws IOException {
     72 		int startPosition = output.position(), total = 0, bytesRead;
     73 		while ((bytesRead = input.read(buffer)) != -1) {
     74 			BufferUtils.copy(buffer, 0, output, bytesRead);
     75 			total += bytesRead;
     76 			output.position(startPosition + total);
     77 		}
     78 		output.position(startPosition);
     79 		return total;
     80 	}
     81 
     82 	/** Copy the data from an {@link InputStream} to a byte array. The stream is not closed. */
     83 	public static byte[] copyStreamToByteArray (InputStream input) throws IOException {
     84 		return copyStreamToByteArray(input, input.available());
     85 	}
     86 
     87 	/** Copy the data from an {@link InputStream} to a byte array. The stream is not closed.
     88 	 * @param estimatedSize Used to allocate the output byte[] to possibly avoid an array copy. */
     89 	public static byte[] copyStreamToByteArray (InputStream input, int estimatedSize) throws IOException {
     90 		ByteArrayOutputStream baos = new OptimizedByteArrayOutputStream(Math.max(0, estimatedSize));
     91 		copyStream(input, baos);
     92 		return baos.toByteArray();
     93 	}
     94 
     95 	/** Calls {@link #copyStreamToString(InputStream, int, String)} using the input's {@link InputStream#available() available} size
     96 	 * and the platform's default charset. */
     97 	public static String copyStreamToString (InputStream input) throws IOException {
     98 		return copyStreamToString(input, input.available(), null);
     99 	}
    100 
    101 	/** Calls {@link #copyStreamToString(InputStream, int, String)} using the platform's default charset. */
    102 	public static String copyStreamToString (InputStream input, int estimatedSize) throws IOException {
    103 		return copyStreamToString(input, estimatedSize, null);
    104 	}
    105 
    106 	/** Copy the data from an {@link InputStream} to a string using the specified charset.
    107 	 * @param estimatedSize Used to allocate the output buffer to possibly avoid an array copy.
    108 	 * @param charset May be null to use the platform's default charset. */
    109 	public static String copyStreamToString (InputStream input, int estimatedSize, String charset) throws IOException {
    110 		InputStreamReader reader = charset == null ? new InputStreamReader(input) : new InputStreamReader(input, charset);
    111 		StringWriter writer = new StringWriter(Math.max(0, estimatedSize));
    112 		char[] buffer = new char[DEFAULT_BUFFER_SIZE];
    113 		int charsRead;
    114 		while ((charsRead = reader.read(buffer)) != -1) {
    115 			writer.write(buffer, 0, charsRead);
    116 		}
    117 		return writer.toString();
    118 	}
    119 
    120 	/** Close and ignore all errors. */
    121 	public static void closeQuietly (Closeable c) {
    122 		if (c != null) {
    123 			try {
    124 				c.close();
    125 			} catch (Exception ignored) {
    126 			}
    127 		}
    128 	}
    129 
    130 	/** A ByteArrayOutputStream which avoids copying of the byte array if possible. */
    131 	static public class OptimizedByteArrayOutputStream extends ByteArrayOutputStream {
    132 		public OptimizedByteArrayOutputStream (int initialSize) {
    133 			super(initialSize);
    134 		}
    135 
    136 		@Override
    137 		public synchronized byte[] toByteArray () {
    138 			if (count == buf.length) return buf;
    139 			return super.toByteArray();
    140 		}
    141 
    142 		public byte[] getBuffer () {
    143 			return buf;
    144 		}
    145 	}
    146 }
    147