All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kiwiproject.io.KiwiIO Maven / Gradle / Ivy

Go to download

Kiwi is a utility library. We really like Google's Guava, and also use Apache Commons. But if they don't have something we need, and we think it is useful, this is where we put it.

There is a newer version: 4.4.0
Show newest version
package org.kiwiproject.io;

import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;

import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

/**
 * Static I/O utilities.
 * 

* The {@code closeQuietly} methods that accept {@link Closeable} were copied directly from Apache Commons I/O and * the deprecation warnings and annotations removed. While they should not be used often, sometimes they might come in * handy so we want to keep them around for posterity. Slight style modifications were made (e.g. replace {@code obj != null} * checks with {@code nonNull(obj}, etc. as well as adding logging. Did not bother copying all the {@code closeQuietly} * methods that took a specific class such as {@link java.io.Reader}, {@link java.io.Writer}, {@link java.net.Socket}, etc. * They all implement {@link Closeable} and were probably only there because those specific classes pre-dated Java 5 when * {@link Closeable} was added to the JDK, and we assume early (pre-Java 5) versions of {@code IOUtils} provided them. */ @UtilityClass @Slf4j public class KiwiIO { /** * Closes a Closeable unconditionally. *

* Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. This is typically used in * finally blocks. *

* Example code: *

*
     * Closeable closeable = null;
     * try {
     *     closeable = new FileReader("foo.txt");
     *     // process closeable
     *     closeable.close();
     * } catch (Exception e) {
     *     // error handling
     * } finally {
     *     IOUtils.closeQuietly(closeable);
     * }
     * 
*

* Closing all streams: *

*
     * try {
     *     return IOUtils.copy(inputStream, outputStream);
     * } finally {
     *     IOUtils.closeQuietly(inputStream);
     *     IOUtils.closeQuietly(outputStream);
     * }
     * 
* * @param closeable the objects to close, may be null or already closed * @implNote Copied from Apache Commons I/O's IOUtils once it became deprecated with the message "Please use * the try-with-resources statement or handle suppressed exceptions manually." * @see Throwable#addSuppressed(java.lang.Throwable) */ public static void closeQuietly(final Closeable closeable) { try { if (nonNull(closeable)) { closeable.close(); } } catch (final IOException ioe) { logCloseException(closeable.getClass(), ioe); } } /** * Closes a Closeable unconditionally. *

* Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. *

* This is typically used in finally blocks to ensure that the closeable is closed * even if an Exception was thrown before the normal close statement was reached. *
* It should not be used to replace the close statement(s) * which should be present for the non-exceptional case. *
* It is only intended to simplify tidying up where normal processing has already failed * and reporting close failure as well is not necessary or useful. *

* Example code: *

*
     * Closeable closeable = null;
     * try {
     *     closeable = new FileReader("foo.txt");
     *     // processing using the closeable; may throw an Exception
     *     closeable.close(); // Normal close - exceptions not ignored
     * } catch (Exception e) {
     *     // error handling
     * } finally {
     *     IOUtils.closeQuietly(closeable); // In case normal close was skipped due to Exception
     * }
     * 
*

* Closing all streams: *
*

     * try {
     *     return IOUtils.copy(inputStream, outputStream);
     * } finally {
     *     IOUtils.closeQuietly(inputStream, outputStream);
     * }
     * 
* * @param closeables the objects to close, may be null or already closed * @implNote Copied from Apache Commons I/O's IOUtils once it became deprecated with the message "Please use * the try-with-resources statement or handle suppressed exceptions manually." * @see #closeQuietly(Closeable) * @see Throwable#addSuppressed(java.lang.Throwable) */ public static void closeQuietly(final Closeable... closeables) { if (isNull(closeables)) { return; } for (final Closeable closeable : closeables) { closeQuietly(closeable); } } /** * Closes an {@link XMLStreamReader} unconditionally. *

* Since {@link XMLStreamReader} does not implement {@link Closeable}, you cannot use a try-with-resources. * * @param xmlStreamReader the {@link XMLStreamReader} to close * @see Throwable#addSuppressed(java.lang.Throwable) */ public static void closeQuietly(XMLStreamReader xmlStreamReader) { if (nonNull(xmlStreamReader)) { try { xmlStreamReader.close(); } catch (Exception e) { logCloseException(XMLStreamReader.class, e); } } } /** * Closes an {@link XMLStreamWriter} unconditionally. *

* Since {@link XMLStreamWriter} does not implement {@link Closeable}, you cannot use a try-with-resources. * * @param xmlStreamWriter the {@link XMLStreamWriter} to close * @see Throwable#addSuppressed(java.lang.Throwable) */ public static void closeQuietly(XMLStreamWriter xmlStreamWriter) { if (nonNull(xmlStreamWriter)) { try { xmlStreamWriter.close(); } catch (Exception e) { logCloseException(XMLStreamWriter.class, e); } } } private static void logCloseException(Class typeOfObject, Exception ex) { String typeSimpleName = typeOfObject.getSimpleName(); LOG.warn("Unexpected error while attempting to close {} quietly (use DEBUG-level for stack trace): {}", typeSimpleName, ex.getMessage()); LOG.debug("Error closing {} instance", typeSimpleName, ex); } /** * Return a newly constructed {@link ByteArrayInputStream} containing the given {@code lines} separated by * the {@link System#lineSeparator()}. * * @param lines the lines to convert * @return a ByteArrayInputStream containing the given lines */ public static ByteArrayInputStream newByteArrayInputStreamOfLines(String... lines) { if (lines.length == 0) { return emptyByteArrayInputStream(); } String joined = Arrays.stream(lines).collect(joining(System.lineSeparator())); byte[] buffer = joined.getBytes(StandardCharsets.UTF_8); return new ByteArrayInputStream(buffer); } /** * Return a newly constructed, empty {@link ByteArrayInputStream}. * * @return new ByteArrayInputStream */ public static ByteArrayInputStream emptyByteArrayInputStream() { return new ByteArrayInputStream(new byte[0]); } /** * Return a {@link List} of {@link String}s from the error stream of the given {@link Process} using {@code UTF-8} * for the String encoding. * * @param process the process * @return the list of UTF-8 encoded strings from the process' error stream */ public static List readLinesFromErrorStreamOf(Process process) { return readLinesFrom(process.getErrorStream(), StandardCharsets.UTF_8); } /** * Return a {@link List} of {@link String}s from the error stream of the given {@link Process} using the specified * {@link Charset} for the String encoding. * * @param process the process * @param charset the charset * @return the list of UTF-8 encoded strings from the process' error stream */ public static List readLinesFromErrorStreamOf(Process process, Charset charset) { return readLinesFrom(process.getErrorStream(), charset); } /** * Return a {@link List} of {@link String}s from the input stream of the given {@link Process} using {@code UTF-8} * for the String encoding. * * @param process the process * @return the list of UTF-8 encoded strings from the process' input stream */ public static List readLinesFromInputStreamOf(Process process) { return readLinesFrom(process.getInputStream(), StandardCharsets.UTF_8); } /** * Return a {@link List} of {@link String}s from the input stream of the given {@link Process} using the specified * {@link Charset} for the String encoding. * * @param process the process * @param charset the charset * @return the list of UTF-8 encoded strings from the process' input stream */ public static List readLinesFromInputStreamOf(Process process, Charset charset) { return readLinesFrom(process.getInputStream(), charset); } /** * Return a {@link List} of {@link String}s from the input stream using the specified {@link Charset} for the * String encoding. * * @param stream the stream * @param charset the charset * @return a list of strings from the input stream, encoded using the specified charset */ public static List readLinesFrom(InputStream stream, Charset charset) { return streamLinesFrom(stream, charset).collect(toList()); } /** * Return a {@link Stream} of {@link String}s from the error stream of the given {@link Process} using {@code UTF-8} * for the String encoding. * * @param process the process * @return the stream of UTF-8 encoded strings from the process' error stream */ public static Stream streamLinesFromErrorStreamOf(Process process) { return streamLinesFrom(process.getErrorStream(), StandardCharsets.UTF_8); } /** * Return a {@link Stream} of {@link String}s from the error stream of the given {@link Process} using the specified * {@link Charset} for the String encoding. * * @param process the process * @param charset the charset * @return the stream of strings from the process' error stream, encoded using the specified charset */ public static Stream streamLinesFromErrorStreamOf(Process process, Charset charset) { return streamLinesFrom(process.getErrorStream(), charset); } /** * Return a {@link Stream} of {@link String}s from the input stream of the given {@link Process} using {@code UTF-8} * for the String encoding. * * @param process the process * @return the stream of UTF-8 encoded strings from the process' input stream */ public static Stream streamLinesFromInputStreamOf(Process process) { return streamLinesFrom(process.getInputStream(), StandardCharsets.UTF_8); } /** * Return a {@link Stream} of {@link String}s from the input stream of the given {@link Process} using the specified * {@link Charset} for the String encoding. * * @param process the process * @param charset the charset * @return the stream of strings from the process' input stream, encoded using the specified charset */ public static Stream streamLinesFromInputStreamOf(Process process, Charset charset) { return streamLinesFrom(process.getInputStream(), charset); } /** * Return a {@link Stream} of {@link String}s from the given {@link InputStream} using the specified {@link Charset} * for the String encoding. * * @param stream the stream * @param charset the charset * @return the stream of strings from the input stream, encoded using the specified charset */ public static Stream streamLinesFrom(InputStream stream, Charset charset) { return new BufferedReader(new InputStreamReader(stream, charset)).lines(); } /** * Read the input stream of the give {@link Process} as a String using {@code UTF-8} as the String encoding. *

* Note that process output may contain one or more lines, which will therefore include line termination * characters within or at the end of the returned string. * * @param process the process * @return the process' input stream as a UTF-8 encoded string * @see Process#getInputStream() */ public static String readInputStreamOf(Process process) { return readInputStreamOf(process, StandardCharsets.UTF_8); } /** * Read the input stream of the give {@link Process} as a String using the the specified {@link Charset} for the * string encoding. *

* Note that process output may contain one or more lines, which will therefore include line termination * characters within or at the end of the returned string. * * @param process the process * @param charset the charset * @return the process' input stream as a string, encoded using the specified charset * @see Process#getInputStream() */ public static String readInputStreamOf(Process process, Charset charset) { return readInputStreamAsString(process.getInputStream(), charset); } /** * Read the error stream of the give {@link Process} as a String using {@code UTF-8} as the string encoding. *

* Note that process output may contain one or more lines, which will therefore include line termination * characters within or at the end of the returned string. * * @param process the process * @return the process' error stream as a UTF-8 encoded string * @see Process#getErrorStream() */ public static String readErrorStreamOf(Process process) { return readErrorStreamOf(process, StandardCharsets.UTF_8); } /** * Read the error stream of the give {@link Process} as a String using the the specified {@link Charset} for the * string encoding. *

* Note that process output may contain one or more lines, which will therefore include line termination * characters within or at the end of the returned string. * * @param process the process * @param charset the charset * @return the process' error stream as a string, encoded using the specified charset * @see Process#getErrorStream() */ public static String readErrorStreamOf(Process process, Charset charset) { return readInputStreamAsString(process.getErrorStream(), charset); } /** * Convert the given {@link InputStream} to a {@code UTF-8} encoded String. * * @param inputStream the input stream * @return the input stream as a UTF-8 encoded string */ public static String readInputStreamAsString(InputStream inputStream) { return readInputStreamAsString(inputStream, StandardCharsets.UTF_8); } /** * Convert the given {@link InputStream} to a String using the given {@link Charset} for the string encoding. * * @param inputStream the input stream * @param charset the charset * @return the input stream as a string, encoded using the specified charset */ public static String readInputStreamAsString(InputStream inputStream, Charset charset) { try { var outputStream = new ByteArrayOutputStream(); inputStream.transferTo(outputStream); return outputStream.toString(charset); } catch (IOException e) { throw new UncheckedIOException("Error converting InputStream to String using Charset " + charset, e); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy