Class IOUtilities

java.lang.Object
com.cedarsoftware.util.IOUtilities

public final class IOUtilities extends Object
Utility class providing robust I/O operations with built-in error handling and resource management.

This class simplifies common I/O tasks such as:

  • Stream transfers and copying
  • Resource closing and flushing
  • Byte array compression/decompression
  • URL connection handling
  • File operations

Key Features:

  • Automatic buffer management for optimal performance
  • GZIP and Deflate compression support
  • Unchecked exception handling for close/flush operations (fail-fast, not silent)
  • Progress tracking through callback mechanism
  • Support for XML stream operations with unchecked exception handling
  • XML stream support: Methods close(XMLStreamReader), close(XMLStreamWriter), and flush(XMLStreamWriter) work with javax.xml.stream classes. These methods require the java.xml module to be present at runtime. If you're using JPMS, add requires java.xml; to your module-info.java if using these methods. For OSGi, ensure your bundle imports the javax.xml.stream package or declare it as an optional import if XML support is not required. The rest of the library does not require java.xml.

Exception Handling Philosophy: All close() and flush() methods in this class throw exceptions as unchecked via ExceptionUtilities.uncheckedThrow(Throwable). This design choice provides:

  • Cleaner code - no try-catch required in finally blocks or cleanup code
  • Better diagnostics - close/flush failures are visible rather than silently swallowed
  • Early problem detection - infrastructure issues surface immediately rather than hiding until later failures
  • Flexibility - callers can catch these as regular exceptions higher in the call stack if desired
While close/flush exceptions are rare, they often indicate serious issues (disk full, network failures, resource exhaustion) that should be diagnosed rather than hidden.

Usage Example:


 // Copy file to output stream
 try (InputStream fis = Files.newInputStream(Paths.get("input.txt"))) {
     try (OutputStream fos = Files.newOutputStream(Paths.get("output.txt"))) {
         IOUtilities.transfer(fis, fos);
     }
 }

 // Compress byte array
 byte[] compressed = IOUtilities.compressBytes(originalBytes);
 byte[] uncompressed = IOUtilities.uncompressBytes(compressed);
 

Security and Performance Configuration:

IOUtilities provides configurable security and performance options through system properties. Most security features have safe defaults but can be customized as needed:

  • io.debug=false — Enable debug logging
  • io.connect.timeout=5000 — Connection timeout (1s-5min)
  • io.read.timeout=30000 — Read timeout (1s-5min)
  • io.max.stream.size=2147483647 — Stream size limit (2GB)
  • io.max.decompression.size=2147483647 — Decompression size limit (2GB)
  • io.path.validation.disabled=false — Path security validation enabled
  • io.url.protocol.validation.disabled=false — URL protocol validation enabled
  • io.allowed.protocols=http,https,file,jar — Allowed URL protocols
  • io.file.protocol.validation.disabled=false — File protocol validation enabled
  • io.debug.detailed.urls=false — Detailed URL logging disabled
  • io.debug.detailed.paths=false — Detailed path logging disabled
Author:
Ken Partlow, John DeRegnaucourt ([email protected])
Copyright (c) Cedar Software LLC

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

License

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.
  • Method Details

    • getInputStream

      public static InputStream getInputStream(URLConnection c)
      Gets an appropriate InputStream from a URLConnection, handling compression if necessary.

      This method automatically detects and handles various compression encodings and optimizes connection performance with appropriate buffer sizing and connection parameters.

      • GZIP ("gzip" or "x-gzip")
      • DEFLATE ("deflate")
      Parameters:
      c - the URLConnection to get the input stream from
      Returns:
      a buffered InputStream, potentially wrapped with a decompressing stream
      Throws:
      IOException - if an I/O error occurs (thrown as unchecked)
    • transfer

      public static void transfer(File f, URLConnection c, IOUtilities.TransferCallback cb)
      Transfers the contents of a File to a URLConnection's output stream.

      Progress can be monitored and the transfer can be cancelled through the callback interface.

      Parameters:
      f - the source File to transfer
      c - the destination URLConnection
      cb - optional callback for progress monitoring and cancellation (may be null)
      Throws:
      IOException - if an I/O error occurs during the transfer (thrown as unchecked)
    • transfer

      public static void transfer(URLConnection c, File f, IOUtilities.TransferCallback cb)
      Transfers the contents of a URLConnection's input stream to a File.

      Progress can be monitored and the transfer can be cancelled through the callback interface. Automatically handles compressed streams.

      Parameters:
      c - the source URLConnection
      f - the destination File
      cb - optional callback for progress monitoring and cancellation (may be null)
      Throws:
      IOException - if an I/O error occurs during the transfer (thrown as unchecked)
    • transfer

      public static void transfer(InputStream s, File f, IOUtilities.TransferCallback cb)
      Transfers the contents of an InputStream to a File.

      Progress can be monitored and the transfer can be cancelled through the callback interface. The output stream is automatically buffered for optimal performance.

      Parameters:
      s - the source InputStream
      f - the destination File
      cb - optional callback for progress monitoring and cancellation (may be null)
      Throws:
      IOException - if an I/O error occurs during the transfer (thrown as unchecked)
    • transfer

      public static void transfer(InputStream in, OutputStream out, IOUtilities.TransferCallback cb)
      Transfers bytes from an input stream to an output stream with optional progress monitoring.

      This method does not close the streams; that responsibility remains with the caller. Progress can be monitored and the transfer can be cancelled through the callback interface. The callback receives a defensive copy of the buffer to prevent race conditions and data corruption.

      Parameters:
      in - the source InputStream
      out - the destination OutputStream
      cb - optional callback for progress monitoring and cancellation (may be null)
      Throws:
      IOException - if an I/O error occurs during transfer (thrown as unchecked)
    • transfer

      public static void transfer(InputStream in, byte[] bytes)
      Reads exactly the specified number of bytes from an InputStream into a byte array.

      This method will continue reading until either the byte array is full or the end of the stream is reached. Uses DataInputStream.readFully for a simpler implementation.

      Parameters:
      in - the InputStream to read from
      bytes - the byte array to fill
      Throws:
      IOException - if the stream ends before the byte array is filled or if any other I/O error occurs (thrown as unchecked)
    • transfer

      public static void transfer(InputStream in, OutputStream out)
      Transfers all bytes from an input stream to an output stream.

      This method does not close the streams; that responsibility remains with the caller. Uses an internal buffer for efficient transfer.

      Parameters:
      in - the source InputStream
      out - the destination OutputStream
      Throws:
      IOException - if an I/O error occurs during transfer (thrown as unchecked)
    • transfer

      public static void transfer(File file, OutputStream out)
      Transfers the contents of a File to an OutputStream.

      The input is automatically buffered for optimal performance. The output stream is flushed after the transfer but not closed.

      Parameters:
      file - the source File
      out - the destination OutputStream
      Throws:
      IOException - if an I/O error occurs during transfer (thrown as unchecked)
    • close

      public static void close(XMLStreamReader reader)
      Closes an XMLStreamReader, throwing any exceptions as unchecked.

      This method can be safely used in finally blocks without requiring a try-catch, as XMLStreamException will be thrown unchecked via ExceptionUtilities.uncheckedThrow(Throwable). This provides cleaner code while ensuring close failures are visible rather than silently swallowed.

      Close exceptions are rare but important - they often indicate serious issues like network failures, resource exhaustion, or data corruption. Making them visible helps diagnose problems earlier.

      Parameters:
      reader - the XMLStreamReader to close (may be null)
      Throws:
      XMLStreamException - if close fails (thrown as unchecked)
    • close

      public static void close(XMLStreamWriter writer)
      Closes an XMLStreamWriter, throwing any exceptions as unchecked.

      This method can be safely used in finally blocks without requiring a try-catch, as XMLStreamException will be thrown unchecked via ExceptionUtilities.uncheckedThrow(Throwable). This provides cleaner code while ensuring close failures are visible rather than silently swallowed.

      Parameters:
      writer - the XMLStreamWriter to close (may be null)
      Throws:
      XMLStreamException - if close fails (thrown as unchecked)
    • close

      public static void close(Closeable c)
      Closes any Closeable resource, throwing any exceptions as unchecked.

      This method can be safely used in finally blocks or cleanup code without requiring a try-catch, as IOException will be thrown unchecked via ExceptionUtilities.uncheckedThrow(Throwable). This provides cleaner code while ensuring close failures are visible rather than silently swallowed.

      Why close exceptions matter: While rare, close failures often indicate serious issues:

      • File streams: Disk full, permission denied, filesystem corruption
      • Network streams: Connection lost, timeout, broken pipe
      • Database connections: Transaction rollback failures, connection pool issues
      • Compressed streams: Incomplete data, corruption, checksum failures
      Making these exceptions visible helps diagnose infrastructure problems early rather than hiding them until they cause more serious failures downstream.

      Parameters:
      c - the Closeable resource to close (may be null)
      Throws:
      IOException - if close fails (thrown as unchecked)
    • flush

      public static void flush(Flushable f)
      Flushes any Flushable resource, throwing any exceptions as unchecked.

      This method can be safely used without requiring a try-catch, as IOException will be thrown unchecked via ExceptionUtilities.uncheckedThrow(Throwable). Flush failures often indicate buffer overflow, disk full, or network issues that should be made visible rather than silently ignored.

      Parameters:
      f - the Flushable resource to flush (may be null)
      Throws:
      IOException - if flush fails (thrown as unchecked)
    • flush

      public static void flush(XMLStreamWriter writer)
      Flushes an XMLStreamWriter, throwing any exceptions as unchecked.

      This method can be safely used without requiring a try-catch, as XMLStreamException will be thrown unchecked via ExceptionUtilities.uncheckedThrow(Throwable). Flush failures often indicate buffer or output stream issues that should be made visible.

      Parameters:
      writer - the XMLStreamWriter to flush (may be null)
      Throws:
      XMLStreamException - if flush fails (thrown as unchecked)
    • inputStreamToBytes

      public static byte[] inputStreamToBytes(InputStream in)
      Converts an InputStream's contents to a byte array.

      This method loads the entire stream into memory, so use with appropriate consideration for memory usage. Uses a default maximum size limit (2GB) to prevent memory exhaustion attacks while allowing reasonable data transfer operations. For custom limits, use inputStreamToBytes(InputStream, int).

      Parameters:
      in - the InputStream to read from
      Returns:
      the byte array containing the stream's contents
      Throws:
      IOException - if an I/O error occurs or the stream exceeds the default size limit (thrown as unchecked)
    • inputStreamToBytes

      public static byte[] inputStreamToBytes(InputStream in, int maxSize)
      Converts an InputStream's contents to a byte array with a maximum size limit.
      Parameters:
      in - the InputStream to read from
      maxSize - the maximum number of bytes to read
      Returns:
      the byte array containing the stream's contents
      Throws:
      IOException - if an I/O error occurs or the stream exceeds maxSize (thrown as unchecked)
    • transfer

      public static void transfer(URLConnection c, byte[] bytes)
      Transfers a byte array to a URLConnection's output stream.

      The output stream is automatically buffered for optimal performance and properly closed after transfer.

      Parameters:
      c - the URLConnection to write to
      bytes - the byte array to transfer
      Throws:
      IOException - if an I/O error occurs during transfer (thrown as unchecked)
    • compressBytes

      public static void compressBytes(ByteArrayOutputStream original, ByteArrayOutputStream compressed)
      Compresses the contents of one ByteArrayOutputStream into another using GZIP compression.

      Uses BEST_SPEED compression level for optimal performance.

      Parameters:
      original - the ByteArrayOutputStream containing the data to compress
      compressed - the ByteArrayOutputStream to receive the compressed data
      Throws:
      IOException - if an I/O error occurs during compression (thrown as unchecked)
    • compressBytes

      public static void compressBytes(FastByteArrayOutputStream original, FastByteArrayOutputStream compressed)
      Compresses the contents of one FastByteArrayOutputStream into another using GZIP compression.

      Uses BEST_SPEED compression level for optimal performance.

      Parameters:
      original - the FastByteArrayOutputStream containing the data to compress
      compressed - the FastByteArrayOutputStream to receive the compressed data
      Throws:
      IOException - if an I/O error occurs during compression (thrown as unchecked)
    • compressBytes

      public static byte[] compressBytes(byte[] bytes)
      Compresses a byte array using GZIP compression.
      Parameters:
      bytes - the byte array to compress
      Returns:
      a new byte array containing the compressed data
      Throws:
      RuntimeException - if compression fails
    • compressBytes

      public static byte[] compressBytes(byte[] bytes, int offset, int len)
      Compresses a portion of a byte array using GZIP compression.
      Parameters:
      bytes - the source byte array
      offset - the starting position in the source array
      len - the number of bytes to compress
      Returns:
      a new byte array containing the compressed data
      Throws:
      RuntimeException - if compression fails
    • uncompressBytes

      public static byte[] uncompressBytes(byte[] bytes)
      Uncompresses a GZIP-compressed byte array with default size limits.

      If the input is not GZIP-compressed, returns the original array unchanged. Uses a default maximum decompressed size (2GB) to prevent zip bomb attacks.

      Parameters:
      bytes - the compressed byte array
      Returns:
      the uncompressed byte array, or the original array if not compressed
      Throws:
      RuntimeException - if decompression fails or exceeds size limits
    • uncompressBytes

      public static byte[] uncompressBytes(byte[] bytes, int offset, int len)
      Uncompresses a portion of a GZIP-compressed byte array with default size limits.

      If the input is not GZIP-compressed, returns the original array unchanged. Uses a default maximum decompressed size (2GB) to prevent zip bomb attacks.

      Parameters:
      bytes - the compressed byte array
      offset - the starting position in the source array
      len - the number of bytes to uncompress
      Returns:
      the uncompressed byte array, or the original array if not compressed
      Throws:
      RuntimeException - if decompression fails or exceeds size limits
    • uncompressBytes

      public static byte[] uncompressBytes(byte[] bytes, int offset, int len, int maxSize)
      Uncompresses a portion of a GZIP-compressed byte array with specified size limit.

      If the input is not GZIP-compressed, returns the original array unchanged.

      Parameters:
      bytes - the compressed byte array
      offset - the starting position in the source array
      len - the number of bytes to uncompress
      maxSize - the maximum allowed decompressed size in bytes
      Returns:
      the uncompressed byte array, or the original array if not compressed
      Throws:
      RuntimeException - if decompression fails or exceeds size limits