Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* Copyright (C) 2006-2014 phloc systems
* http://www.phloc.com
* office[at]phloc[dot]com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.phloc.commons.io.streams;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.EOFException;
import java.io.Flushable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.WillClose;
import javax.annotation.WillNotClose;
import javax.annotation.concurrent.Immutable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.phloc.commons.CGlobal;
import com.phloc.commons.ValueEnforcer;
import com.phloc.commons.annotations.Nonempty;
import com.phloc.commons.annotations.PresentForCodeCoverage;
import com.phloc.commons.annotations.ReturnsMutableCopy;
import com.phloc.commons.callback.INonThrowingRunnableWithParameter;
import com.phloc.commons.charset.CharsetManager;
import com.phloc.commons.io.IInputStreamProvider;
import com.phloc.commons.mock.IMockException;
import com.phloc.commons.mutable.MutableLong;
import com.phloc.commons.state.ESuccess;
import com.phloc.commons.stats.IStatisticsHandlerSize;
import com.phloc.commons.stats.StatisticsManager;
/**
* Some very basic IO stream utility stuff. All input stream (=reading) related
* stuff is quite null aware, where on writing an output stream may
* never be null.
*
* @author Philip Helger
*/
@Immutable
public final class StreamUtils
{
/** buffer size for copy operations */
private static final int DEFAULT_BUFSIZE = 16 * CGlobal.BYTES_PER_KILOBYTE;
/** The logger to use. */
private static final Logger s_aLogger = LoggerFactory.getLogger (StreamUtils.class);
private static final IStatisticsHandlerSize s_aByteSizeHdl = StatisticsManager.getSizeHandler (StreamUtils.class.getName () +
"$COPY");
private static final IStatisticsHandlerSize s_aCharSizeHdl = StatisticsManager.getSizeHandler (StreamUtils.class.getName () +
"$COPYCHARS");
@PresentForCodeCoverage
@SuppressWarnings ("unused")
private static final StreamUtils s_aInstance = new StreamUtils ();
private StreamUtils ()
{}
/**
* Check if the passed exception is a known EOF exception.
*
* @param t
* The throwable/exception to be checked. May be null.
* @return true if it is a user-created EOF exception
*/
public static boolean isKnownEOFException (@Nullable final Throwable t)
{
return t != null && isKnownEOFException (t.getClass ());
}
/**
* Check if the passed class is a known EOF exception class.
*
* @param aClass
* The class to be checked. May be null.
* @return true if it is a known EOF exception class.
*/
public static boolean isKnownEOFException (@Nullable final Class > aClass)
{
if (aClass == null)
return false;
final String sClass = aClass.getName ();
return sClass.equals ("java.io.EOFException") ||
sClass.equals ("org.mortbay.jetty.EofException") ||
sClass.equals ("org.eclipse.jetty.io.EofException") ||
sClass.equals ("org.apache.catalina.connector.ClientAbortException");
}
/**
* Close the passed object, without trying to call flush on it.
*
* @param aCloseable
* The object to be closed. May be null.
* @return {@link ESuccess#SUCCESS} if the object was successfully closed.
*/
@Nonnull
public static ESuccess closeWithoutFlush (@Nullable @WillClose final Closeable aCloseable)
{
if (aCloseable != null)
{
try
{
// close stream
aCloseable.close ();
return ESuccess.SUCCESS;
}
catch (final IOException ex)
{
if (!isKnownEOFException (ex))
s_aLogger.error ("Failed to close stream " + aCloseable.getClass ().getName (),
ex instanceof IMockException ? null : ex);
}
}
return ESuccess.FAILURE;
}
/**
* Close the passed stream by encapsulating the declared {@link IOException}.
* If the passed object also implements the {@link Flushable} interface, it is
* tried to be flushed before it is closed.
*
* @param aCloseable
* The object to be closed. May be null.
* @return {@link ESuccess} if the object was successfully closed.
*/
@Nonnull
public static ESuccess close (@Nullable @WillClose final Closeable aCloseable)
{
if (aCloseable != null)
{
try
{
// flush object (if available)
if (aCloseable instanceof Flushable)
flush ((Flushable) aCloseable);
// close object
aCloseable.close ();
return ESuccess.SUCCESS;
}
catch (final NullPointerException ex)
{
// Happens if a java.io.FilterInputStream or java.io.FilterOutputStream
// has no underlying stream!
}
catch (final IOException ex)
{
if (!isKnownEOFException (ex))
s_aLogger.error ("Failed to close object " + aCloseable.getClass ().getName (),
ex instanceof IMockException ? null : ex);
}
}
return ESuccess.FAILURE;
}
/**
* Special close version for {@link Socket} as they are not implementing
* {@link Closeable} :(
*
* @param aSocket
* The socket to be closed. May be null.
* @return {@link ESuccess} if the object was successfully closed.
*/
@Nonnull
public static ESuccess close (@Nullable @WillClose final Socket aSocket)
{
if (aSocket != null && !aSocket.isClosed ())
{
try
{
// close object
aSocket.close ();
return ESuccess.SUCCESS;
}
catch (final IOException ex)
{
if (!isKnownEOFException (ex))
s_aLogger.error ("Failed to close socket " + aSocket.getClass ().getName (),
ex instanceof IMockException ? null : ex);
}
}
return ESuccess.FAILURE;
}
/**
* Special close version for {@link ServerSocket} as they are not implementing
* {@link Closeable} :(
*
* @param aSocket
* The socket to be closed. May be null.
* @return {@link ESuccess} if the object was successfully closed.
*/
@Nonnull
public static ESuccess close (@Nullable @WillClose final ServerSocket aSocket)
{
if (aSocket != null && !aSocket.isClosed ())
{
try
{
// close object
aSocket.close ();
return ESuccess.SUCCESS;
}
catch (final IOException ex)
{
if (!isKnownEOFException (ex))
s_aLogger.error ("Failed to close server socket " + aSocket.getClass ().getName (),
ex instanceof IMockException ? null : ex);
}
}
return ESuccess.FAILURE;
}
/**
* Flush the passed object encapsulating the declared {@link IOException}.
*
* @param aFlushable
* The flushable to be flushed. May be null.
* @return {@link ESuccess#SUCCESS} if the object was successfully flushed.
*/
@Nonnull
public static ESuccess flush (@Nullable final Flushable aFlushable)
{
if (aFlushable != null)
try
{
aFlushable.flush ();
return ESuccess.SUCCESS;
}
catch (final NullPointerException ex)
{
// Happens if a java.io.FilterOutputStream is already closed!
}
catch (final IOException ex)
{
if (!isKnownEOFException (ex))
s_aLogger.error ("Failed to flush object " + aFlushable.getClass ().getName (),
ex instanceof IMockException ? null : ex);
}
return ESuccess.FAILURE;
}
/**
* Pass the content of the given input stream to the given output stream. Both
* the input stream and the output stream are automatically closed.
*
* @param aIS
* The input stream to read from. May be null.
* Automatically closed!
* @param aOS
* The output stream to write to. May be null.
* Automatically closed!
* @return {@link ESuccess#SUCCESS} if copying took place,
* {@link ESuccess#FAILURE} otherwise
*/
@Nonnull
public static ESuccess copyInputStreamToOutputStreamAndCloseOS (@WillClose @Nullable final InputStream aIS,
@WillClose @Nullable final OutputStream aOS)
{
try
{
return copyInputStreamToOutputStream (aIS, aOS, new byte [DEFAULT_BUFSIZE], (MutableLong) null, (Long) null);
}
finally
{
close (aOS);
}
}
/**
* Pass the content of the given input stream to the given output stream. Both
* the input stream and the output stream are automatically closed.
*
* @param aIS
* The input stream to read from. May be null.
* Automatically closed!
* @param aOS
* The output stream to write to. May be null.
* Automatically closed!
* @param nLimit
* The maximum number of bytes to be copied to the output stream. Must
* be ≥ 0.
* @return {@link ESuccess#SUCCESS} if copying took place,
* {@link ESuccess#FAILURE} otherwise
*/
@Nonnull
public static ESuccess copyInputStreamToOutputStreamWithLimitAndCloseOS (@WillClose @Nullable final InputStream aIS,
@WillClose @Nullable final OutputStream aOS,
@Nonnegative final long nLimit)
{
try
{
return copyInputStreamToOutputStream (aIS,
aOS,
new byte [DEFAULT_BUFSIZE],
(MutableLong) null,
Long.valueOf (nLimit));
}
finally
{
close (aOS);
}
}
/**
* Pass the content of the given input stream to the given output stream. The
* input stream is automatically closed, whereas the output stream stays open!
*
* @param aIS
* The input stream to read from. May be null.
* Automatically closed!
* @param aOS
* The output stream to write to. May be null. Not
* automatically closed!
* @return {@link ESuccess#SUCCESS} if copying took place,
* {@link ESuccess#FAILURE} otherwise
*/
@Nonnull
public static ESuccess copyInputStreamToOutputStream (@WillClose @Nullable final InputStream aIS,
@WillNotClose @Nullable final OutputStream aOS)
{
return copyInputStreamToOutputStream (aIS, aOS, new byte [DEFAULT_BUFSIZE], (MutableLong) null, (Long) null);
}
/**
* Pass the content of the given input stream to the given output stream. The
* input stream is automatically closed, whereas the output stream stays open!
*
* @param aIS
* The input stream to read from. May be null.
* Automatically closed!
* @param aOS
* The output stream to write to. May be null. Not
* automatically closed!
* @param aCopyByteCount
* An optional mutable long object that will receive the total number
* of copied bytes. Note: and optional old value is overwritten!
* @return {@link ESuccess#SUCCESS} if copying took place,
* {@link ESuccess#FAILURE} otherwise
*/
@Nonnull
public static ESuccess copyInputStreamToOutputStream (@WillClose @Nullable final InputStream aIS,
@WillNotClose @Nullable final OutputStream aOS,
@Nullable final MutableLong aCopyByteCount)
{
return copyInputStreamToOutputStream (aIS, aOS, new byte [DEFAULT_BUFSIZE], aCopyByteCount, (Long) null);
}
/**
* Pass the content of the given input stream to the given output stream. The
* input stream is automatically closed, whereas the output stream stays open!
*
* @param aIS
* The input stream to read from. May be null.
* Automatically closed!
* @param aOS
* The output stream to write to. May be null. Not
* automatically closed!
* @param nLimit
* The maximum number of bytes to be copied to the output stream. Must
* be ≥ 0.
* @return {@link ESuccess#SUCCESS} if copying took place,
* {@link ESuccess#FAILURE} otherwise
*/
@Nonnull
public static ESuccess copyInputStreamToOutputStreamWithLimit (@WillClose @Nullable final InputStream aIS,
@WillNotClose @Nullable final OutputStream aOS,
@Nonnegative final long nLimit)
{
return copyInputStreamToOutputStream (aIS,
aOS,
new byte [DEFAULT_BUFSIZE],
(MutableLong) null,
Long.valueOf (nLimit));
}
/**
* Pass the content of the given input stream to the given output stream. The
* input stream is automatically closed, whereas the output stream stays open!
*
* @param aIS
* The input stream to read from. May be null.
* Automatically closed!
* @param aOS
* The output stream to write to. May be null. Not
* automatically closed!
* @param aBuffer
* The buffer to use. May not be null.
* @return {@link ESuccess#SUCCESS} if copying took place,
* {@link ESuccess#FAILURE} otherwise
*/
@Nonnull
public static ESuccess copyInputStreamToOutputStream (@WillClose @Nullable final InputStream aIS,
@WillNotClose @Nullable final OutputStream aOS,
@Nonnull final byte [] aBuffer)
{
return copyInputStreamToOutputStream (aIS, aOS, aBuffer, (MutableLong) null, (Long) null);
}
@Nonnegative
private static long _copyInputStreamToOutputStream (@Nonnull @WillNotClose final InputStream aIS,
@Nonnull @WillNotClose final OutputStream aOS,
@Nonnull @WillNotClose final byte [] aBuffer) throws IOException
{
long nTotalBytesWritten = 0;
int nBytesRead;
while ((nBytesRead = aIS.read (aBuffer, 0, aBuffer.length)) > -1)
{
aOS.write (aBuffer, 0, nBytesRead);
nTotalBytesWritten += nBytesRead;
}
return nTotalBytesWritten;
}
@Nonnegative
private static long _copyInputStreamToOutputStreamWithLimit (@Nonnull @WillNotClose final InputStream aIS,
@Nonnull @WillNotClose final OutputStream aOS,
@Nonnull final byte [] aBuffer,
@Nonnegative final long nLimit) throws IOException
{
long nRest = nLimit;
long nTotalBytesWritten = 0;
while (true)
{
// if nRest is smaller than aBuffer.length, which is an int, it is safe to
// cast nRest also to an int!
final int nBytesToRead = nRest >= aBuffer.length ? aBuffer.length : (int) nRest;
if (nBytesToRead == 0)
break;
final int nBytesRead = aIS.read (aBuffer, 0, nBytesToRead);
if (nBytesRead == -1)
{
// EOF
break;
}
if (nBytesRead > 0)
{
// At least one byte read
aOS.write (aBuffer, 0, nBytesRead);
nTotalBytesWritten += nBytesRead;
nRest -= nBytesRead;
}
}
return nTotalBytesWritten;
}
/**
* Pass the content of the given input stream to the given output stream. The
* input stream is automatically closed, whereas the output stream stays open!
*
* @param aIS
* The input stream to read from. May be null.
* Automatically closed!
* @param aOS
* The output stream to write to. May be null. Not
* automatically closed!
* @param aBuffer
* The buffer to use. May not be null.
* @param aCopyByteCount
* An optional mutable long object that will receive the total number
* of copied bytes. Note: and optional old value is overwritten!
* @return {@link ESuccess#SUCCESS} if copying took place,
* {@link ESuccess#FAILURE} otherwise
*/
@Nonnull
public static ESuccess copyInputStreamToOutputStream (@WillClose @Nullable final InputStream aIS,
@WillNotClose @Nullable final OutputStream aOS,
@Nonnull @Nonempty final byte [] aBuffer,
@Nullable final MutableLong aCopyByteCount)
{
return copyInputStreamToOutputStream (aIS, aOS, aBuffer, aCopyByteCount, (Long) null);
}
/**
* Pass the content of the given input stream to the given output stream. The
* input stream is automatically closed, whereas the output stream stays open!
*
* @param aIS
* The input stream to read from. May be null.
* Automatically closed!
* @param aOS
* The output stream to write to. May be null. Not
* automatically closed!
* @param aBuffer
* The buffer to use. May not be null.
* @param aCopyByteCount
* An optional mutable long object that will receive the total number
* of copied bytes. Note: and optional old value is overwritten!
* @param aLimit
* An optional maximum number of bytes to copied from the input stream
* to the output stream. May be null to indicate no limit,
* meaning all bytes are copied.
* @return {@link ESuccess#SUCCESS} if copying took place,
* {@link ESuccess#FAILURE} otherwise
*/
@Nonnull
public static ESuccess copyInputStreamToOutputStream (@WillClose @Nullable final InputStream aIS,
@WillNotClose @Nullable final OutputStream aOS,
@Nonnull @Nonempty final byte [] aBuffer,
@Nullable final MutableLong aCopyByteCount,
@Nullable final Long aLimit)
{
ValueEnforcer.notEmpty (aBuffer, "Buffer");
if (aLimit != null && aLimit.longValue () < 0)
throw new IllegalArgumentException ("Limit may not be negative!");
try
{
if (aIS != null && aOS != null)
{
// both streams are not null
long nTotalBytesCopied;
if (aLimit == null)
nTotalBytesCopied = _copyInputStreamToOutputStream (aIS, aOS, aBuffer);
else
nTotalBytesCopied = _copyInputStreamToOutputStreamWithLimit (aIS, aOS, aBuffer, aLimit.longValue ());
// Add to statistics
s_aByteSizeHdl.addSize (nTotalBytesCopied);
// Remember copied bytes?
if (aCopyByteCount != null)
aCopyByteCount.set (nTotalBytesCopied);
return ESuccess.SUCCESS;
}
}
catch (final IOException ex)
{
if (!isKnownEOFException (ex))
s_aLogger.error ("Failed to copy from stream to stream", ex instanceof IMockException ? null : ex);
}
finally
{
// Ensure input stream is closed, even if output stream is null
close (aIS);
}
return ESuccess.FAILURE;
}
/**
* Get the number of available bytes in the passed input stream.
*
* @param aIS
* The input stream to use. May be null.
* @return 0 in case of an error or if the parameter was null.
*/
public static int getAvailable (@Nullable final InputStream aIS)
{
if (aIS != null)
try
{
return aIS.available ();
}
catch (final IOException ex)
{
// Fall through
}
return 0;
}
/**
* Get a byte buffer with all the available content of the passed input
* stream.
*
* @param aIS
* The source input stream. May not be null.
* @return A new {@link NonBlockingByteArrayOutputStream} with all available
* content inside.
*/
@Nonnull
public static NonBlockingByteArrayOutputStream getCopy (@Nonnull @WillClose final InputStream aIS)
{
final int nAvailable = Math.max (DEFAULT_BUFSIZE, getAvailable (aIS));
final NonBlockingByteArrayOutputStream aBAOS = new NonBlockingByteArrayOutputStream (nAvailable);
copyInputStreamToOutputStreamAndCloseOS (aIS, aBAOS);
return aBAOS;
}
/**
* Get a byte buffer with all the available content of the passed input
* stream.
*
* @param aIS
* The source input stream. May not be null.
* @param nLimit
* The maximum number of bytes to be copied to the output stream. Must
* be ≥ 0.
* @return A new {@link NonBlockingByteArrayOutputStream} with all available
* content inside.
*/
@Nonnull
public static NonBlockingByteArrayOutputStream getCopyWithLimit (@Nonnull @WillClose final InputStream aIS,
@Nonnegative final long nLimit)
{
final int nAvailable = Math.max (DEFAULT_BUFSIZE, getAvailable (aIS));
final NonBlockingByteArrayOutputStream aBAOS = new NonBlockingByteArrayOutputStream (nAvailable);
copyInputStreamToOutputStreamWithLimitAndCloseOS (aIS, aBAOS, nLimit);
return aBAOS;
}
/**
* Read all bytes from the passed input stream into a byte array.
*
* @param aISP
* The input stream provider to read from. May be null .
* @return The byte array or null if the parameter or the
* resolved input stream is null.
*/
@Nullable
public static byte [] getAllBytes (@Nullable final IInputStreamProvider aISP)
{
if (aISP == null)
return null;
return getAllBytes (aISP.getInputStream ());
}
/**
* Read all bytes from the passed input stream into a byte array.
*
* @param aIS
* The input stream to read from. May be null.
* @return The byte array or null if the input stream is
* null.
*/
@Nullable
public static byte [] getAllBytes (@Nullable @WillClose final InputStream aIS)
{
if (aIS == null)
return null;
return getCopy (aIS).toByteArray ();
}
/**
* Read all bytes from the passed input stream into a string.
*
* @param aISP
* The input stream provider to read from. May be null .
* @param sCharset
* The charset to use. May not be null .
* @return The String or null if the parameter or the resolved
* input stream is null.
*/
@Nullable
@Deprecated
public static String getAllBytesAsString (@Nullable final IInputStreamProvider aISP,
@Nonnull @Nonempty final String sCharset)
{
if (aISP == null)
return null;
return getAllBytesAsString (aISP.getInputStream (), sCharset);
}
/**
* Read all bytes from the passed input stream into a string.
*
* @param aISP
* The input stream provider to read from. May be null .
* @param aCharset
* The charset to use. May not be null .
* @return The String or null if the parameter or the resolved
* input stream is null.
*/
@Nullable
public static String getAllBytesAsString (@Nullable final IInputStreamProvider aISP,
@Nonnull @Nonempty final Charset aCharset)
{
if (aISP == null)
return null;
return getAllBytesAsString (aISP.getInputStream (), aCharset);
}
/**
* Read all bytes from the passed input stream into a string.
*
* @param aIS
* The input stream to read from. May be null.
* @param sCharset
* The charset to use. May not be null .
* @return The String or null if the input stream is
* null.
*/
@Nullable
@Deprecated
public static String getAllBytesAsString (@Nullable @WillClose final InputStream aIS,
@Nonnull @Nonempty final String sCharset)
{
ValueEnforcer.notEmpty (sCharset, "Charset");
if (aIS == null)
return null;
return getCopy (aIS).getAsString (sCharset);
}
/**
* Read all bytes from the passed input stream into a string.
*
* @param aIS
* The input stream to read from. May be null.
* @param aCharset
* The charset to use. May not be null .
* @return The String or null if the input stream is
* null.
*/
@Nullable
public static String getAllBytesAsString (@Nullable @WillClose final InputStream aIS,
@Nonnull @Nonempty final Charset aCharset)
{
ValueEnforcer.notNull (aCharset, "Charset");
if (aIS == null)
return null;
return getCopy (aIS).getAsString (aCharset);
}
/**
* Pass the content of the given reader to the given writer. The reader and
* the writer are automatically closed!
*
* @param aReader
* The reader to read from. May be null. Automatically
* closed!
* @param aWriter
* The writer to write to. May be null. Automatically
* closed!
* @return {@link ESuccess#SUCCESS} if copying took place,
* {@link ESuccess#FAILURE} otherwise
*/
@Nonnull
public static ESuccess copyReaderToWriterAndCloseWriter (@WillClose @Nullable final Reader aReader,
@WillClose @Nullable final Writer aWriter)
{
try
{
return copyReaderToWriter (aReader, aWriter, new char [DEFAULT_BUFSIZE], (MutableLong) null, (Long) null);
}
finally
{
close (aWriter);
}
}
/**
* Pass the content of the given reader to the given writer. The reader and
* the writer are automatically closed!
*
* @param aReader
* The reader to read from. May be null. Automatically
* closed!
* @param aWriter
* The writer to write to. May be null. Automatically
* closed!
* @param nLimit
* The maximum number of chars to be copied to the writer. Must be ≥
* 0.
* @return {@link ESuccess#SUCCESS} if copying took place,
* {@link ESuccess#FAILURE} otherwise
*/
@Nonnull
public static ESuccess copyReaderToWriterWithLimitAndCloseWriter (@WillClose @Nullable final Reader aReader,
@WillClose @Nullable final Writer aWriter,
@Nonnegative final long nLimit)
{
try
{
return copyReaderToWriter (aReader,
aWriter,
new char [DEFAULT_BUFSIZE],
(MutableLong) null,
Long.valueOf (nLimit));
}
finally
{
close (aWriter);
}
}
/**
* Pass the content of the given reader to the given writer. The reader is
* automatically closed, whereas the writer stays open!
*
* @param aReader
* The reader to read from. May be null. Automatically
* closed!
* @param aWriter
* The writer to write to. May be null. Not automatically
* closed!
* @return {@link ESuccess#SUCCESS} if copying took place,
* {@link ESuccess#FAILURE} otherwise
*/
@Nonnull
public static ESuccess copyReaderToWriter (@WillClose @Nullable final Reader aReader,
@WillNotClose @Nullable final Writer aWriter)
{
return copyReaderToWriter (aReader, aWriter, new char [DEFAULT_BUFSIZE], (MutableLong) null, (Long) null);
}
/**
* Pass the content of the given reader to the given writer. The reader is
* automatically closed, whereas the writer stays open!
*
* @param aReader
* The reader to read from. May be null. Automatically
* closed!
* @param aWriter
* The writer to write to. May be null. Not automatically
* closed!
* @param aCopyCharCount
* An optional mutable long object that will receive the total number
* of copied characters. Note: and optional old value is overwritten!
* @return {@link ESuccess#SUCCESS} if copying took place,
* {@link ESuccess#FAILURE} otherwise
*/
@Nonnull
public static ESuccess copyReaderToWriter (@WillClose @Nullable final Reader aReader,
@WillNotClose @Nullable final Writer aWriter,
@Nullable final MutableLong aCopyCharCount)
{
return copyReaderToWriter (aReader, aWriter, new char [DEFAULT_BUFSIZE], aCopyCharCount, (Long) null);
}
/**
* Pass the content of the given reader to the given writer. The reader is
* automatically closed, whereas the writer stays open!
*
* @param aReader
* The reader to read from. May be null. Automatically
* closed!
* @param aWriter
* The writer to write to. May be null. Not automatically
* closed!
* @param aBuffer
* The buffer to use. May not be null.
* @return {@link ESuccess#SUCCESS} if copying took place,
* {@link ESuccess#FAILURE} otherwise
*/
@Nonnull
public static ESuccess copyReaderToWriter (@WillClose @Nullable final Reader aReader,
@WillNotClose @Nullable final Writer aWriter,
@Nonnull final char [] aBuffer)
{
return copyReaderToWriter (aReader, aWriter, aBuffer, (MutableLong) null, (Long) null);
}
/**
* Pass the content of the given reader to the given writer. The reader is
* automatically closed, whereas the writer stays open!
*
* @param aReader
* The reader to read from. May be null. Automatically
* closed!
* @param aWriter
* The writer to write to. May be null. Not automatically
* closed!
* @param nLimit
* The maximum number of chars to be copied to the writer. Must be ≥
* 0.
* @return {@link ESuccess#SUCCESS} if copying took place,
* {@link ESuccess#FAILURE} otherwise
*/
@Nonnull
public static ESuccess copyReaderToWriterWithLimit (@WillClose @Nullable final Reader aReader,
@WillNotClose @Nullable final Writer aWriter,
final long nLimit)
{
return copyReaderToWriter (aReader, aWriter, new char [DEFAULT_BUFSIZE], (MutableLong) null, Long.valueOf (nLimit));
}
@Nonnegative
private static long _copyReaderToWriter (@Nonnull final Reader aReader,
@Nonnull final Writer aWriter,
@Nonnull final char [] aBuffer) throws IOException
{
long nTotalCharsWritten = 0;
int nCharsRead;
while ((nCharsRead = aReader.read (aBuffer, 0, aBuffer.length)) > -1)
{
aWriter.write (aBuffer, 0, nCharsRead);
nTotalCharsWritten += nCharsRead;
}
return nTotalCharsWritten;
}
@Nonnegative
private static long _copyReaderToWriterWithLimit (@Nonnull final Reader aReader,
@Nonnull final Writer aWriter,
@Nonnull final char [] aBuffer,
@Nonnegative final long nLimit) throws IOException
{
long nRest = nLimit;
long nTotalCharsWritten = 0;
while (true)
{
// if nRest is smaller than aBuffer.length, which is an int, it is safe to
// cast nRest also to an int!
final int nCharsToRead = nRest >= aBuffer.length ? aBuffer.length : (int) nRest;
if (nCharsToRead == 0)
break;
final int nCharsRead = aReader.read (aBuffer, 0, nCharsToRead);
if (nCharsRead == -1)
{
// EOF
break;
}
if (nCharsRead > 0)
{
// At least one byte read
aWriter.write (aBuffer, 0, nCharsRead);
nTotalCharsWritten += nCharsRead;
nRest -= nCharsRead;
}
}
return nTotalCharsWritten;
}
/**
* Pass the content of the given reader to the given writer. The reader is
* automatically closed, whereas the writer stays open!
*
* @param aReader
* The reader to read from. May be null. Automatically
* closed!
* @param aWriter
* The writer to write to. May be null. Not automatically
* closed!
* @param aBuffer
* The buffer to use. May not be null.
* @param aCopyCharCount
* An optional mutable long object that will receive the total number
* of copied characters. Note: and optional old value is overwritten!
* @return {@link ESuccess#SUCCESS} if copying took place,
* {@link ESuccess#FAILURE} otherwise
*/
@Nonnull
public static ESuccess copyReaderToWriter (@WillClose @Nullable final Reader aReader,
@WillNotClose @Nullable final Writer aWriter,
@Nonnull @Nonempty final char [] aBuffer,
@Nullable final MutableLong aCopyCharCount)
{
return copyReaderToWriter (aReader, aWriter, aBuffer, aCopyCharCount, (Long) null);
}
/**
* Pass the content of the given reader to the given writer. The reader is
* automatically closed, whereas the writer stays open!
*
* @param aReader
* The reader to read from. May be null. Automatically
* closed!
* @param aWriter
* The writer to write to. May be null. Not automatically
* closed!
* @param aBuffer
* The buffer to use. May not be null.
* @param aCopyCharCount
* An optional mutable long object that will receive the total number
* of copied characters. Note: and optional old value is overwritten!
* @param aLimit
* An optional maximum number of chars to copied from the reader to the
* writer. May be null to indicate no limit, meaning all
* chars are copied.
* @return {@link ESuccess#SUCCESS} if copying took place,
* {@link ESuccess#FAILURE} otherwise
*/
@Nonnull
public static ESuccess copyReaderToWriter (@WillClose @Nullable final Reader aReader,
@WillNotClose @Nullable final Writer aWriter,
@Nonnull @Nonempty final char [] aBuffer,
@Nullable final MutableLong aCopyCharCount,
@Nullable final Long aLimit)
{
ValueEnforcer.notEmpty (aBuffer, "Buffer");
if (aLimit != null && aLimit.longValue () < 0)
throw new IllegalArgumentException ("Limit may not be negative!");
try
{
if (aReader != null && aWriter != null)
{
// both streams are not null
final long nTotalCharsCopied = aLimit == null ? _copyReaderToWriter (aReader, aWriter, aBuffer)
: _copyReaderToWriterWithLimit (aReader,
aWriter,
aBuffer,
aLimit.longValue ());
// Add to statistics
s_aCharSizeHdl.addSize (nTotalCharsCopied);
// Remember number of copied characters
if (aCopyCharCount != null)
aCopyCharCount.set (nTotalCharsCopied);
return ESuccess.SUCCESS;
}
}
catch (final IOException ex)
{
if (!isKnownEOFException (ex))
s_aLogger.error ("Failed to copy from reader to writer", ex instanceof IMockException ? null : ex);
}
finally
{
// Ensure reader is closed, even if writer is null
close (aReader);
}
return ESuccess.FAILURE;
}
@Nonnull
public static NonBlockingStringWriter getCopy (@Nonnull @WillClose final Reader aReader)
{
final NonBlockingStringWriter aWriter = new NonBlockingStringWriter (DEFAULT_BUFSIZE);
copyReaderToWriterAndCloseWriter (aReader, aWriter);
return aWriter;
}
@Nonnull
public static NonBlockingStringWriter getCopyWithLimit (@Nonnull @WillClose final Reader aReader,
@Nonnegative final long nLimit)
{
final NonBlockingStringWriter aWriter = new NonBlockingStringWriter (DEFAULT_BUFSIZE);
copyReaderToWriterWithLimitAndCloseWriter (aReader, aWriter, nLimit);
return aWriter;
}
/**
* Read all characters from the passed reader into a char array.
*
* @param aReader
* The reader to read from. May be null.
* @return The character array or null if the reader is
* null.
*/
@Nullable
public static char [] getAllCharacters (@Nullable @WillClose final Reader aReader)
{
if (aReader == null)
return null;
return getCopy (aReader).getAsCharArray ();
}
/**
* Read all characters from the passed reader into a String.
*
* @param aReader
* The reader to read from. May be null.
* @return The character array or null if the reader is
* null.
*/
@Nullable
public static String getAllCharactersAsString (@Nullable @WillClose final Reader aReader)
{
if (aReader == null)
return null;
return getCopy (aReader).getAsString ();
}
/**
* Get the content of the passed Spring resource as one big string in the
* passed character set.
*
* @param aISP
* The resource to read. May not be null.
* @param sCharset
* The character set to use. May not be null.
* @return null if the resolved input stream is null
* , the content otherwise.
*/
@Nullable
@ReturnsMutableCopy
@Deprecated
public static List readStreamLines (@Nullable final IInputStreamProvider aISP,
@Nonnull @Nonempty final String sCharset)
{
return readStreamLines (aISP, sCharset, 0, CGlobal.ILLEGAL_UINT);
}
/**
* Get the content of the passed Spring resource as one big string in the
* passed character set.
*
* @param aISP
* The resource to read. May not be null.
* @param aCharset
* The character set to use. May not be null.
* @return null if the resolved input stream is null
* , the content otherwise.
*/
@Nullable
@ReturnsMutableCopy
public static List readStreamLines (@Nullable final IInputStreamProvider aISP,
@Nonnull final Charset aCharset)
{
return readStreamLines (aISP, aCharset, 0, CGlobal.ILLEGAL_UINT);
}
/**
* Get the content of the passed Spring resource as one big string in the
* passed character set.
*
* @param aISP
* The resource to read. May be null.
* @param sCharset
* The character set to use. May not be null.
* @param nLinesToSkip
* The 0-based index of the first line to read. Pass in 0 to indicate
* to read everything.
* @param nLinesToRead
* The number of lines to read. Pass in {@link CGlobal#ILLEGAL_UINT} to
* indicate that all lines should be read. If the number passed here
* exceeds the number of lines in the file, nothing happens.
* @return null if the resolved input stream is null
* , the content otherwise.
*/
@Nullable
@ReturnsMutableCopy
@Deprecated
public static List readStreamLines (@Nullable final IInputStreamProvider aISP,
@Nonnull @Nonempty final String sCharset,
@Nonnegative final int nLinesToSkip,
final int nLinesToRead)
{
if (aISP == null)
return null;
return readStreamLines (aISP.getInputStream (), sCharset, nLinesToSkip, nLinesToRead);
}
/**
* Get the content of the passed Spring resource as one big string in the
* passed character set.
*
* @param aISP
* The resource to read. May be null.
* @param aCharset
* The character set to use. May not be null.
* @param nLinesToSkip
* The 0-based index of the first line to read. Pass in 0 to indicate
* to read everything.
* @param nLinesToRead
* The number of lines to read. Pass in {@link CGlobal#ILLEGAL_UINT} to
* indicate that all lines should be read. If the number passed here
* exceeds the number of lines in the file, nothing happens.
* @return null if the resolved input stream is null
* , the content otherwise.
*/
@Nullable
@ReturnsMutableCopy
public static List readStreamLines (@Nullable final IInputStreamProvider aISP,
@Nonnull final Charset aCharset,
@Nonnegative final int nLinesToSkip,
final int nLinesToRead)
{
if (aISP == null)
return null;
return readStreamLines (aISP.getInputStream (), aCharset, nLinesToSkip, nLinesToRead);
}
/**
* Get the content of the passed stream as a list of lines in the passed
* character set.
*
* @param aIS
* The input stream to read from. May be null.
* @param sCharset
* The character set to use. May not be null.
* @return null if the input stream is null, the
* content lines otherwise.
*/
@Nullable
@ReturnsMutableCopy
@Deprecated
public static List readStreamLines (@WillClose @Nullable final InputStream aIS,
@Nonnull @Nonempty final String sCharset)
{
return readStreamLines (aIS, sCharset, 0, CGlobal.ILLEGAL_UINT);
}
/**
* Get the content of the passed stream as a list of lines in the passed
* character set.
*
* @param aIS
* The input stream to read from. May be null.
* @param aCharset
* The character set to use. May not be null.
* @return null if the input stream is null, the
* content lines otherwise.
*/
@Nullable
@ReturnsMutableCopy
public static List readStreamLines (@WillClose @Nullable final InputStream aIS,
@Nonnull @Nonempty final Charset aCharset)
{
return readStreamLines (aIS, aCharset, 0, CGlobal.ILLEGAL_UINT);
}
/**
* Get the content of the passed stream as a list of lines in the passed
* character set.
*
* @param aIS
* The input stream to read from. May be null.
* @param sCharset
* The character set to use. May not be null.
* @param aTargetList
* The list to be filled with the lines. May not be null.
*/
@Deprecated
public static void readStreamLines (@WillClose @Nullable final InputStream aIS,
@Nonnull @Nonempty final String sCharset,
@Nonnull final List aTargetList)
{
if (aIS != null)
readStreamLines (aIS, sCharset, 0, CGlobal.ILLEGAL_UINT, new INonThrowingRunnableWithParameter ()
{
public void run (final String sLine)
{
aTargetList.add (sLine);
}
});
}
/**
* Get the content of the passed stream as a list of lines in the passed
* character set.
*
* @param aIS
* The input stream to read from. May be null.
* @param aCharset
* The character set to use. May not be null.
* @param aTargetList
* The list to be filled with the lines. May not be null.
*/
public static void readStreamLines (@WillClose @Nullable final InputStream aIS,
@Nonnull final Charset aCharset,
@Nonnull final List aTargetList)
{
if (aIS != null)
readStreamLines (aIS, aCharset, 0, CGlobal.ILLEGAL_UINT, new INonThrowingRunnableWithParameter ()
{
public void run (final String sLine)
{
aTargetList.add (sLine);
}
});
}
/**
* Get the content of the passed stream as a list of lines in the passed
* character set.
*
* @param aIS
* The input stream to read from. May be null.
* @param sCharset
* The character set to use. May not be null.
* @param nLinesToSkip
* The 0-based index of the first line to read. Pass in 0 to indicate
* to read everything.
* @param nLinesToRead
* The number of lines to read. Pass in {@link CGlobal#ILLEGAL_UINT} to
* indicate that all lines should be read. If the number passed here
* exceeds the number of lines in the file, nothing happens.
* @return null if the input stream is null, the
* content lines otherwise.
*/
@Nullable
@ReturnsMutableCopy
@Deprecated
public static List readStreamLines (@WillClose @Nullable final InputStream aIS,
@Nonnull @Nonempty final String sCharset,
@Nonnegative final int nLinesToSkip,
final int nLinesToRead)
{
if (aIS == null)
return null;
// Read stream and collect all read lines in a list
final List ret = new ArrayList ();
readStreamLines (aIS, sCharset, nLinesToSkip, nLinesToRead, new INonThrowingRunnableWithParameter ()
{
public void run (final String sLine)
{
ret.add (sLine);
}
});
return ret;
}
/**
* Get the content of the passed stream as a list of lines in the passed
* character set.
*
* @param aIS
* The input stream to read from. May be null.
* @param aCharset
* The character set to use. May not be null.
* @param nLinesToSkip
* The 0-based index of the first line to read. Pass in 0 to indicate
* to read everything.
* @param nLinesToRead
* The number of lines to read. Pass in {@link CGlobal#ILLEGAL_UINT} to
* indicate that all lines should be read. If the number passed here
* exceeds the number of lines in the file, nothing happens.
* @return null if the input stream is null, the
* content lines otherwise.
*/
@Nullable
@ReturnsMutableCopy
public static List readStreamLines (@WillClose @Nullable final InputStream aIS,
@Nonnull final Charset aCharset,
@Nonnegative final int nLinesToSkip,
final int nLinesToRead)
{
if (aIS == null)
return null;
// Read stream and collect all read lines in a list
final List ret = new ArrayList ();
readStreamLines (aIS, aCharset, nLinesToSkip, nLinesToRead, new INonThrowingRunnableWithParameter ()
{
public void run (final String sLine)
{
ret.add (sLine);
}
});
return ret;
}
/**
* Read the complete content of the passed stream and pass each line
* separately to the passed callback.
*
* @param aIS
* The input stream to read from. May be null.
* @param sCharset
* The character set to use. May not be null.
* @param aLineCallback
* The callback that is invoked for all read lines. Each passed line
* does NOT contain the line delimiter!
*/
@Deprecated
public static void readStreamLines (@WillClose @Nullable final InputStream aIS,
@Nonnull @Nonempty final String sCharset,
@Nonnull final INonThrowingRunnableWithParameter aLineCallback)
{
readStreamLines (aIS, sCharset, 0, CGlobal.ILLEGAL_UINT, aLineCallback);
}
/**
* Read the complete content of the passed stream and pass each line
* separately to the passed callback.
*
* @param aIS
* The input stream to read from. May be null.
* @param aCharset
* The character set to use. May not be null.
* @param aLineCallback
* The callback that is invoked for all read lines. Each passed line
* does NOT contain the line delimiter!
*/
public static void readStreamLines (@WillClose @Nullable final InputStream aIS,
@Nonnull @Nonempty final Charset aCharset,
@Nonnull final INonThrowingRunnableWithParameter aLineCallback)
{
readStreamLines (aIS, aCharset, 0, CGlobal.ILLEGAL_UINT, aLineCallback);
}
private static void _readFromReader (final int nLinesToSkip,
final int nLinesToRead,
final INonThrowingRunnableWithParameter aLineCallback,
final boolean bReadAllLines,
final NonBlockingBufferedReader aBR) throws IOException
{
// Skip all requested lines
String sLine;
for (int i = 0; i < nLinesToSkip; ++i)
{
sLine = aBR.readLine ();
if (sLine == null)
break;
}
if (bReadAllLines)
{
// Read all lines
while (true)
{
sLine = aBR.readLine ();
if (sLine == null)
break;
aLineCallback.run (sLine);
}
}
else
{
// Read only a certain amount of lines
int nRead = 0;
while (true)
{
sLine = aBR.readLine ();
if (sLine == null)
break;
aLineCallback.run (sLine);
++nRead;
if (nRead >= nLinesToRead)
break;
}
}
}
/**
* Read the content of the passed stream line by line and invoking a callback
* on all matching lines.
*
* @param aIS
* The input stream to read from. May be null.
* @param aCharset
* The character set to use. May not be null.
* @param nLinesToSkip
* The 0-based index of the first line to read. Pass in 0 to indicate
* to read everything.
* @param nLinesToRead
* The number of lines to read. Pass in {@link CGlobal#ILLEGAL_UINT} to
* indicate that all lines should be read. If the number passed here
* exceeds the number of lines in the file, nothing happens.
* @param aLineCallback
* The callback that is invoked for all read lines. Each passed line
* does NOT contain the line delimiter! Note: it is not invoked for
* skipped lines!
*/
public static void readStreamLines (@WillClose @Nullable final InputStream aIS,
@Nonnull @Nonempty final Charset aCharset,
@Nonnegative final int nLinesToSkip,
final int nLinesToRead,
@Nonnull final INonThrowingRunnableWithParameter aLineCallback)
{
ValueEnforcer.notNull (aCharset, "Charset");
ValueEnforcer.isGE0 (nLinesToSkip, "LinesToSkip");
final boolean bReadAllLines = nLinesToRead == CGlobal.ILLEGAL_UINT;
if (nLinesToRead < 0 && !bReadAllLines)
throw new IllegalArgumentException ("Line count may not be that negative: " + nLinesToRead);
ValueEnforcer.notNull (aLineCallback, "LineCallback");
if (aIS != null)
try
{
// Start the action only if there is something to read
if (bReadAllLines || nLinesToRead > 0)
{
NonBlockingBufferedReader aBR = null;
try
{
// read with the passed charset
aBR = new NonBlockingBufferedReader (createReader (aIS, aCharset));
_readFromReader (nLinesToSkip, nLinesToRead, aLineCallback, bReadAllLines, aBR);
}
catch (final IOException ex)
{
s_aLogger.error ("Failed to read from input stream", ex instanceof IMockException ? null : ex);
}
finally
{
// Close buffered reader
close (aBR);
}
}
}
finally
{
// Close input stream in case something went wrong with the buffered
// reader.
close (aIS);
}
}
/**
* Read the content of the passed stream line by line and invoking a callback
* on all matching lines.
*
* @param aIS
* The input stream to read from. May be null.
* @param sCharset
* The character set to use. May not be null.
* @param nLinesToSkip
* The 0-based index of the first line to read. Pass in 0 to indicate
* to read everything.
* @param nLinesToRead
* The number of lines to read. Pass in {@link CGlobal#ILLEGAL_UINT} to
* indicate that all lines should be read. If the number passed here
* exceeds the number of lines in the file, nothing happens.
* @param aLineCallback
* The callback that is invoked for all read lines. Each passed line
* does NOT contain the line delimiter! Note: it is not invoked for
* skipped lines!
*/
@Deprecated
public static void readStreamLines (@WillClose @Nullable final InputStream aIS,
@Nonnull @Nonempty final String sCharset,
@Nonnegative final int nLinesToSkip,
final int nLinesToRead,
@Nonnull final INonThrowingRunnableWithParameter aLineCallback)
{
ValueEnforcer.notNull (sCharset, "Charset");
ValueEnforcer.isGE0 (nLinesToSkip, "LinesToSkip");
final boolean bReadAllLines = nLinesToRead == CGlobal.ILLEGAL_UINT;
if (nLinesToRead < 0 && !bReadAllLines)
throw new IllegalArgumentException ("Line count may not be that negative: " + nLinesToRead);
ValueEnforcer.notNull (aLineCallback, "LineCallback");
if (aIS != null)
try
{
// Start the action only if there is something to read
if (bReadAllLines || nLinesToRead > 0)
{
NonBlockingBufferedReader aBR = null;
try
{
// read with the passed charset
aBR = new NonBlockingBufferedReader (createReader (aIS, sCharset));
_readFromReader (nLinesToSkip, nLinesToRead, aLineCallback, bReadAllLines, aBR);
}
catch (final IOException ex)
{
s_aLogger.error ("Failed to read from input stream", ex instanceof IMockException ? null : ex);
}
finally
{
// Close buffered reader
close (aBR);
}
}
}
finally
{
// Close input stream in case something went wrong with the buffered
// reader.
close (aIS);
}
}
/**
* Write bytes to an {@link OutputStream}.
*
* @param aOS
* The output stream to write to. May not be null. Is
* closed independent of error or success.
* @param aBuf
* The byte array from which is to be written. May not be
* null.
* @param nOfs
* The 0-based index to the first byte in the array to be written. May
* not be < 0.
* @param nLen
* The non-negative amount of bytes to be written. May not be < 0.
* @return {@link ESuccess}
*/
@Nonnull
public static ESuccess writeStream (@WillClose @Nonnull final OutputStream aOS,
@Nonnull final byte [] aBuf,
@Nonnegative final int nOfs,
@Nonnegative final int nLen)
{
ValueEnforcer.notNull (aOS, "OutputStream");
ValueEnforcer.isArrayOfsLen (aBuf, nOfs, nLen);
try
{
aOS.write (aBuf, nOfs, nLen);
aOS.flush ();
return ESuccess.SUCCESS;
}
catch (final IOException ex)
{
s_aLogger.error ("Failed to write to output stream", ex instanceof IMockException ? null : ex);
return ESuccess.FAILURE;
}
finally
{
close (aOS);
}
}
/**
* Write bytes to an {@link OutputStream}.
*
* @param aOS
* The output stream to write to. May not be null. Is
* closed independent of error or success.
* @param aBuf
* The byte array to be written. May not be null.
* @return {@link ESuccess}
*/
@Nonnull
public static ESuccess writeStream (@WillClose @Nonnull final OutputStream aOS, @Nonnull final byte [] aBuf)
{
return writeStream (aOS, aBuf, 0, aBuf.length);
}
/**
* Write bytes to an {@link OutputStream}.
*
* @param aOS
* The output stream to write to. May not be null. Is
* closed independent of error or success.
* @param sContent
* The string to be written. May not be null.
* @param sCharset
* The charset to be used, to convert the String to a byte array.
* @return {@link ESuccess}
*/
@Nonnull
@Deprecated
public static ESuccess writeStream (@WillClose @Nonnull final OutputStream aOS,
@Nonnull final String sContent,
@Nonnull @Nonempty final String sCharset)
{
ValueEnforcer.notNull (sContent, "Content");
ValueEnforcer.notEmpty (sCharset, "Charset");
return writeStream (aOS, CharsetManager.getAsBytes (sContent, sCharset));
}
/**
* Write bytes to an {@link OutputStream}.
*
* @param aOS
* The output stream to write to. May not be null. Is
* closed independent of error or success.
* @param sContent
* The string to be written. May not be null.
* @param aCharset
* The charset to be used, to convert the String to a byte array.
* @return {@link ESuccess}
*/
@Nonnull
public static ESuccess writeStream (@WillClose @Nonnull final OutputStream aOS,
@Nonnull final String sContent,
@Nonnull final Charset aCharset)
{
ValueEnforcer.notNull (sContent, "Content");
ValueEnforcer.notNull (aCharset, "Charset");
return writeStream (aOS, CharsetManager.getAsBytes (sContent, aCharset));
}
@Nonnull
public static NonBlockingStringReader createReader (@Nonnull final String sText)
{
return new NonBlockingStringReader (sText);
}
@Nonnull
public static NonBlockingStringReader createReader (@Nonnull final char [] aChars)
{
return new NonBlockingStringReader (aChars);
}
@Nullable
@Deprecated
public static InputStreamReader createReader (@Nullable final InputStream aIS, @Nonnull final String sCharset)
{
try
{
return aIS == null ? null : new InputStreamReader (aIS, sCharset);
}
catch (final UnsupportedEncodingException ex)
{
throw new IllegalArgumentException ("Failed to create Reader for charset '" + sCharset + "'", ex);
}
}
@Nullable
public static InputStreamReader createReader (@Nullable final InputStream aIS, @Nonnull final Charset aCharset)
{
return aIS == null ? null : new InputStreamReader (aIS, aCharset);
}
@Nullable
@Deprecated
public static OutputStreamWriter createWriter (@Nullable final OutputStream aOS, @Nonnull final String sCharset)
{
try
{
return aOS == null ? null : new OutputStreamWriter (aOS, sCharset);
}
catch (final UnsupportedEncodingException ex)
{
throw new IllegalArgumentException ("Failed to create Writer for charset '" + sCharset + "'", ex);
}
}
@Nullable
public static OutputStreamWriter createWriter (@Nullable final OutputStream aOS, @Nonnull final Charset aCharset)
{
return aOS == null ? null : new OutputStreamWriter (aOS, aCharset);
}
/**
* Fully skip the passed amounts in the input stream. Only forward skipping is
* possible!
*
* @param aIS
* The input stream to skip in.
* @param nBytesToSkip
* The number of bytes to skip. Must be ≥ 0.
* @throws IOException
* In case something goes wrong internally
*/
public static void skipFully (@Nonnull final InputStream aIS, @Nonnegative final long nBytesToSkip) throws IOException
{
ValueEnforcer.notNull (aIS, "InputStream");
ValueEnforcer.isGE0 (nBytesToSkip, "BytesToSkip");
long nRemaining = nBytesToSkip;
while (nRemaining > 0)
{
// May only return a partial skip
final long nSkipped = aIS.skip (nRemaining);
if (nSkipped == 0)
{
// Check if we're at the end of the file or not
// -> blocking read!
if (aIS.read () == -1)
{
throw new EOFException ("Failed to skip a total of " +
nBytesToSkip +
" bytes on input stream. Only skipped " +
(nBytesToSkip - nRemaining) +
" bytes so far!");
}
nRemaining--;
}
else
{
// Skipped at least one char
nRemaining -= nSkipped;
}
}
}
/**
* Read the whole buffer from the input stream.
*
* @param aIS
* The input stream to read from. May not be null.
* @param aBuffer
* The buffer to read from. May not be null.
* @throws IOException
* In case reading fails
*/
public static void readFully (@Nonnull final InputStream aIS, @Nonnull final byte [] aBuffer) throws IOException
{
readFully (aIS, aBuffer, 0, aBuffer.length);
}
/**
* Read the whole buffer from the input stream.
*
* @param aIS
* The input stream to read from. May not be null.
* @param aBuffer
* The buffer to read from. May not be null.
* @param nOfs
* The offset into the destination buffer to use. May not be < 0.
* @param nLen
* The number of bytes to read into the destination buffer to use. May
* not be < 0.
* @return The number of read bytes
* @throws IOException
* In case reading fails
*/
@Nonnegative
public static int readFully (@Nonnull final InputStream aIS,
@Nonnull final byte [] aBuffer,
@Nonnegative final int nOfs,
@Nonnegative final int nLen) throws IOException
{
ValueEnforcer.notNull (aIS, "InputStream");
ValueEnforcer.isArrayOfsLen (aBuffer, nOfs, nLen);
int nTotalBytesRead = 0;
while (nTotalBytesRead < nLen)
{
final int nBytesRead = aIS.read (aBuffer, nOfs + nTotalBytesRead, nLen - nTotalBytesRead);
if (nBytesRead < 0)
throw new EOFException ("Failed to read a total of " +
nLen +
" bytes from input stream. Only read " +
nTotalBytesRead +
" bytes so far.");
nTotalBytesRead += nBytesRead;
}
return nTotalBytesRead;
}
public static boolean isBuffered (@Nullable final InputStream aIS)
{
return aIS instanceof BufferedInputStream ||
aIS instanceof NonBlockingBufferedInputStream ||
aIS instanceof ByteArrayInputStream ||
aIS instanceof NonBlockingByteArrayInputStream ||
aIS instanceof ByteBufferInputStream ||
(aIS instanceof WrappedInputStream && isBuffered (((WrappedInputStream) aIS).getWrappedInputStream ()));
}
@Nullable
public static InputStream getBuffered (@Nullable final InputStream aIS)
{
return aIS == null || isBuffered (aIS) ? aIS : new NonBlockingBufferedInputStream (aIS);
}
public static boolean isBuffered (@Nullable final OutputStream aOS)
{
return aOS instanceof BufferedOutputStream ||
aOS instanceof NonBlockingBufferedOutputStream ||
aOS instanceof ByteArrayOutputStream ||
aOS instanceof NonBlockingByteArrayOutputStream ||
aOS instanceof ByteBufferOutputStream ||
(aOS instanceof WrappedOutputStream && isBuffered (((WrappedOutputStream) aOS).getWrappedOutputStream ()));
}
@Nullable
public static OutputStream getBuffered (@Nullable final OutputStream aOS)
{
return aOS == null || isBuffered (aOS) ? aOS : new NonBlockingBufferedOutputStream (aOS);
}
public static boolean isBuffered (@Nullable final Reader aReader)
{
return aReader instanceof BufferedReader ||
aReader instanceof NonBlockingBufferedReader ||
aReader instanceof StringReader ||
aReader instanceof NonBlockingStringReader ||
(aReader instanceof WrappedReader && isBuffered (((WrappedReader) aReader).getWrappedReader ()));
}
@Nullable
public static Reader getBuffered (@Nullable final Reader aReader)
{
return aReader == null || isBuffered (aReader) ? aReader : new NonBlockingBufferedReader (aReader);
}
public static boolean isBuffered (@Nullable final Writer aWriter)
{
return aWriter instanceof BufferedWriter ||
aWriter instanceof NonBlockingBufferedWriter ||
aWriter instanceof StringWriter ||
aWriter instanceof NonBlockingStringWriter ||
(aWriter instanceof WrappedWriter && isBuffered (((WrappedWriter) aWriter).getWrappedWriter ()));
}
@Nullable
public static Writer getBuffered (@Nullable final Writer aWriter)
{
return aWriter == null || isBuffered (aWriter) ? aWriter : new NonBlockingBufferedWriter (aWriter);
}
}