RTEditor/src/main/java/com/onegravity/rteditor/utils/io/IOUtils.java
public static long copyLarge(Reader input, Writer output, final long inputOffset, final long length, char[] buffer)
            throws IOException {
        if (inputOffset > 0) {
            skipFully(input, inputOffset);
        }
        if (length == 0) {
            return 0;
        }
        int bytesToRead = buffer.length;
        if (length > 0 && length < buffer.length) {
            bytesToRead = (int) length;
        }
        int read;
        long totalRead = 0;
        while (bytesToRead > 0 && EOF != (read = input.read(buffer, 0, bytesToRead))) {
            output.write(buffer, 0, read);
            totalRead += read;
            if (length > 0) { // only adjust length if not reading to the end
                // Note the cast must work because buffer.length is an integer
                bytesToRead = (int) Math.min(length - totalRead, buffer.length);
            }
        }
        return totalRead;
    }
public static long copyLarge(Reader input, Writer output, final long inputOffset, final long length, char[] buffer)
            throws IOException {
        if (inputOffset > 0) {
            skipFully(input, inputOffset);
        }
        if (length == 0) {
            return 0;
        }
        int bytesToRead = buffer.length;
        if (length > 0 && length < buffer.length) {
            bytesToRead = (int) length;
        }
        int read;
        long totalRead = 0;
        while (bytesToRead > 0 && EOF != (read = input.read(buffer, 0, bytesToRead))) {
            output.write(buffer, 0, read);
            totalRead += read;
            if (length > 0) { // only adjust length if not reading to the end
                // Note the cast must work because buffer.length is an integer
                bytesToRead = (int) Math.min(length - totalRead, buffer.length);
            }
        }
        return totalRead;
    }
public static long copyLarge ( Reader input , Writer output , final long inputOffset , final long length , char [ ] buffer ) throws IOException { if ( inputOffset > 0 ) { skipFully ( input , inputOffset ) ; } if ( length == 0 ) { return 0 ; } int bytesToRead = buffer . length ; if ( length > 0 && length < buffer . length ) { bytesToRead = ( int ) length ; } int read ; long totalRead = 0 ; while ( bytesToRead > 0 && EOF != ( read = input . read ( buffer , 0 , bytesToRead ) ) ) { output . write ( buffer , 0 , read ) ; totalRead += read ; if ( length > 0 ) { // only adjust length if not reading to the end // Note the cast must work because buffer.length is an integer bytesToRead = ( int ) Math . min ( length - totalRead , buffer . length ) ; } } return totalRead ; }
Copy some or all chars from a large (over 2GB) <code>InputStream</code> to an
<code>OutputStream</code>, optionally skipping input chars.
<p/>
This method uses the provided buffer, so there is no need to use a
<code>BufferedReader</code>.
<p/>

@param input       the <code>Reader</code> to read from
@param output      the <code>Writer</code> to write to
@param inputOffset : number of chars to skip from input before copying
-ve values are ignored
@param length      : number of chars to copy. -ve means all
@param buffer      the buffer to be used for the copy
@return the number of chars copied
@throws NullPointerException if the input or output is null
@throws IOException          if an I/O error occurs
@since 2.2
Copy some or all chars from a large ( over 2GB ) <code > InputStream< / code > to an <code > OutputStream< / code > optionally skipping input chars . <p / > This method uses the provided buffer so there is no need to use a <code > BufferedReader< / code > . <p / >