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