Class BufferedFileChannelInputStream

java.lang.Object
java.io.InputStream
org.apache.commons.io.input.BufferedFileChannelInputStream
All Implemented Interfaces:
Closeable, AutoCloseable

public final class BufferedFileChannelInputStream extends InputStream
InputStream implementation which uses direct buffer to read a file to avoid extra copy of data between Java and native memory which happens when using BufferedInputStream. Unfortunately, this is not something already available in JDK, sun.nio.ch.ChannelInputStream supports reading a file using NIO, but does not support buffering.

This class was ported and adapted from Apache Spark commit 933dc6cb7b3de1d8ccaf73d124d6eb95b947ed19 where it was called NioBufferedFileInputStream.

Since:
2.9.0
  • Field Details

    • byteBuffer

      private final ByteBuffer byteBuffer
    • fileChannel

      private final FileChannel fileChannel
    • DIRECT_BUFFER_CLASS

      private static final Class<?> DIRECT_BUFFER_CLASS
  • Constructor Details

    • BufferedFileChannelInputStream

      public BufferedFileChannelInputStream(File file) throws IOException
      Constructs a new instance for the given File.
      Parameters:
      file - The file to stream.
      Throws:
      IOException - If an I/O error occurs
    • BufferedFileChannelInputStream

      public BufferedFileChannelInputStream(File file, int bufferSizeInBytes) throws IOException
      Constructs a new instance for the given File and buffer size.
      Parameters:
      file - The file to stream.
      bufferSizeInBytes - buffer size.
      Throws:
      IOException - If an I/O error occurs
    • BufferedFileChannelInputStream

      public BufferedFileChannelInputStream(Path path) throws IOException
      Constructs a new instance for the given Path.
      Parameters:
      path - The path to stream.
      Throws:
      IOException - If an I/O error occurs
    • BufferedFileChannelInputStream

      public BufferedFileChannelInputStream(Path path, int bufferSizeInBytes) throws IOException
      Constructs a new instance for the given Path and buffer size.
      Parameters:
      path - The path to stream.
      bufferSizeInBytes - buffer size.
      Throws:
      IOException - If an I/O error occurs
  • Method Details

    • getDirectBufferClass

      private static Class<?> getDirectBufferClass()
    • isDirectBuffer

      private static boolean isDirectBuffer(Object object)
    • available

      public int available() throws IOException
      Overrides:
      available in class InputStream
      Throws:
      IOException
    • clean

      private void clean(ByteBuffer buffer)
      Attempts to clean up a ByteBuffer if it is direct or memory-mapped. This uses an *unsafe* Sun API that will cause errors if one attempts to read from the disposed buffer. However, neither the bytes allocated to direct buffers nor file descriptors opened for memory-mapped buffers put pressure on the garbage collector. Waiting for garbage collection may lead to the depletion of off-heap memory or huge numbers of open files. There's unfortunately no standard API to manually dispose of these kinds of buffers.
      Parameters:
      buffer - the buffer to clean.
    • cleanDirectBuffer

      private void cleanDirectBuffer(ByteBuffer buffer)
      In Java 8, the type of DirectBuffer.cleaner() was sun.misc.Cleaner, and it was possible to access the method sun.misc.Cleaner.clean() to invoke it. The type changed to jdk.internal.ref.Cleaner in later JDKs, and the .clean() method is not accessible even with reflection. However sun.misc.Unsafe added a invokeCleaner() method in JDK 9+ and this is still accessible with reflection.
      Parameters:
      buffer - the buffer to clean. must be a DirectBuffer.
    • close

      public void close() throws IOException
      Specified by:
      close in interface AutoCloseable
      Specified by:
      close in interface Closeable
      Overrides:
      close in class InputStream
      Throws:
      IOException
    • read

      public int read() throws IOException
      Specified by:
      read in class InputStream
      Throws:
      IOException
    • read

      public int read(byte[] b, int offset, int len) throws IOException
      Overrides:
      read in class InputStream
      Throws:
      IOException
    • refill

      private boolean refill() throws IOException
      Checks whether data is left to be read from the input stream.
      Returns:
      true if data is left, false otherwise
      Throws:
      IOException
    • skip

      public long skip(long n) throws IOException
      Overrides:
      skip in class InputStream
      Throws:
      IOException
    • skipFromFileChannel

      private long skipFromFileChannel(long n) throws IOException
      Throws:
      IOException