/******************************************************************************* * Copyright (c) 2007 Bruno Medeiros and other Contributors. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bruno Medeiros - initial implementation *******************************************************************************/ package melnorme.utilbox.misc; import java.io.BufferedOutputStream; import java.io.BufferedWriter; import java.io.CharArrayWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; import java.nio.charset.Charset; /** * Miscellaneous stream utilities. */ public class StreamUtil { public static final int EOF = -1; private static IOException createFailedToReadExpected(int length, int totalRead) { return new IOException("Failed to read requested amount of characters. " + "Read: " + totalRead + " of total requested: " + length); } /** Reads and returns all bytes from given inputStream until an EOF is read. * Closes inputStream afterwards. */ public static IByteSequence readAllBytesFromStream(InputStream inputStream) throws IOException { return readAllBytesFromStream(inputStream, 32); } /** Reads and returns all bytes from given inputStream until an EOF is read. * Closes inputStream afterwards. * ByteArray buffer is initialized to given capacity. */ public static IByteSequence readAllBytesFromStream(InputStream inputStream, int capacity) throws IOException { try { final int BUFFER_SIZE = 1024; byte[] buffer = new byte[BUFFER_SIZE]; ByteArrayOutputStreamExt bytes = new ByteArrayOutputStreamExt(capacity); int read; while((read = inputStream.read(buffer)) != EOF) { bytes.write(buffer, 0, read); } return bytes; } finally { inputStream.close(); } } /** Reads and returns all chars from given reader until an EOF is read. * Closes reader afterwards. */ public static CharArrayWriter readAllCharsFromReader(Reader reader) throws IOException { try { final int BUFFER_SIZE = 1024; char[] buffer = new char[BUFFER_SIZE]; CharArrayWriter chars = new CharArrayWriter(); int read; while((read = reader.read(buffer)) != EOF) { chars.write(buffer, 0, read); } return chars; } finally { reader.close(); } } /** Reads all chars from given reader until an EOF is read, and returns them as a String. * Closes reader afterwards. */ public static String readStringFromReader(Reader reader) throws IOException { return readAllCharsFromReader(reader).toString(); } /** Reads given length amount of chars from given reader, and returns them in a char[]. * Throws IOException if it fails to read given length amount of elements. * Closes reader afterwards. */ public static char[] readRequiredAmountFromReader(Reader reader, int length) throws IOException { char[] chars = readCharAmountFromReader(reader, length); if(chars.length != length) { throw createFailedToReadExpected(length, chars.length); } return chars; } /** Attempts to read given length amount of chars from given reader, and returns them in a char[]. * Closes reader afterwards. */ public static char[] readCharAmountFromReader(Reader reader, int length) throws IOException { try { char[] chars = new char[length]; int totalRead = 0; do { int read = reader.read(chars, totalRead, length - totalRead); if (read == -1) { break; } totalRead += read; } while (totalRead != length); return chars; } finally { reader.close(); } } /** Writes given bytes array to given outputStream. * Closes outputStream afterwards. */ public static void writeBytesToStream(byte[] bytes, OutputStream outputStream) throws IOException { // A BufferedOutputStream is likely not necessary since this is a one-time array write BufferedOutputStream bos = new BufferedOutputStream(outputStream); try { bos.write(bytes); } finally { bos.close(); } } /** Writes given chars array to given writer. * Close writer afterwards. */ public static void writeCharsToWriter(char[] chars, Writer writer) throws IOException { BufferedWriter bw = new BufferedWriter(writer); try { bw.write(chars); } finally { bw.close(); } } /** Writes given string to given writer. * Close writer afterwards. */ public static void writeStringToWriter(String string, Writer writer) throws IOException { BufferedWriter bw = new BufferedWriter(writer); try { bw.write(string); } finally { bw.close(); } } /** Writes given string to given stream, using given charset */ public static void writeStringToStream(String string, OutputStream stream, Charset charset) throws IOException { OutputStreamWriter osw = new OutputStreamWriter(stream, charset); try { osw.append(string); osw.flush(); } finally { osw.close(); } } /** Copies given length amount of bytes from given inputStream to given outputStream. * Alternatively, if length == -1, copy all bytes in inputStream until EOF. * @throws IOException if it fails to read given length amount of elements. */ public static void copyBytesToStream(InputStream inputStream, OutputStream outputStream, int length) throws IOException { final int BUFFER_SIZE = 1024; byte[] buffer = new byte[BUFFER_SIZE]; int totalRead = 0; do { int readReqLen = (length == -1) ? BUFFER_SIZE : Math.min(BUFFER_SIZE, length - totalRead); int read = inputStream.read(buffer, 0, readReqLen); if (read == -1) { if (length != -1) { throw createFailedToReadExpected(length, totalRead); } else { return; // Nothing more to copy. } } totalRead += read; outputStream.write(buffer, 0, read); } while (totalRead != length); } /** Copies all bytes in given inputStream (until EOF) to given outputStream. * Closes inputStream and outputStream. */ public static void copyStream(InputStream inputStream, OutputStream outputStream) throws IOException { copyStream(inputStream, outputStream, true); } /** Copies all bytes in given inputStream (until EOF) to given outputStream. * Closes inputStream and also outputStream if given closeOut is true. */ public static void copyStream(InputStream inputStream, OutputStream outputStream, boolean closeOut) throws IOException { try { copyBytesToStream(inputStream, outputStream, -1); } finally { try { inputStream.close(); } finally { if(closeOut) { outputStream.close(); } } } } /** Closes given inputStream, either ignoring IOExceptions, * or rethrowing them unchecked, according to given rethrowAsUnchecked. */ public static void uncheckedClose(InputStream inStream, boolean rethrowAsUnchecked) { try { inStream.close(); } catch (IOException e) { if(rethrowAsUnchecked) throw melnorme.utilbox.core.ExceptionAdapter.unchecked(e); } } /** Closes given reader, either ignoring IOExceptions, * or rethrowing them unchecked, according to given rethrowAsUnchecked. */ public static void uncheckedClose(Reader reader, boolean rethrowAsUnchecked) { try { reader.close(); } catch (IOException e) { if(rethrowAsUnchecked) throw melnorme.utilbox.core.ExceptionAdapter.unchecked(e); } } }