Library enhancement proposal for copying data from/to Reader/Writer InputStream/OutputStream

Patrick Reinhart patrick at reini.net
Thu Nov 20 18:30:00 UTC 2014


Hi Pavel,
> Am 20.11.2014 um 10:22 schrieb Pavel Rappo <pavel.rappo at oracle.com>:
> 
> There is at least one method in the JDK with similar characteristics: java.nio.file.Files#copy(java.io.InputStream, java.io.OutputStream)
> But, (1) it has a private access (2) even if we made it public I doubt java.nio.file.Files would be a good place for it
> 

I would suggest to introduce a separate IOUtil class holding such utility methods. Additionally to copyTo() and copyFrom() method could be added later for more intuitive usage. Also the copy method within the Files method could be replaced with a static reference to the IOUtil class.


> P.S. The thing that confuses me though, is the progress consumer. I believe this feature is rarely needed (at least in a way you described it).
> If you want to do something like this, you should probably go asynchronous with full blown solution like what they have in javax.swing.SwingWorker.
> 
> -Pavel

The method having a IntConsumer I have already discussed with some other colleagues and they suggested to better use a IntPredicate in order to have the possibility to interrupt the copy process, without having to interrupt any threads. Additionally there is still the possibility to use such a Predicate for counting the total or using the information for other possibilities.

Here’s implementation example for Input-/OutputStream (similar code would apply for Reader/Writer):

    /**
     * Reads all bytes from an input stream and writes them to an output stream.
     *
     * @param source the input stream to read from
     * @param target the path to the file
     *
     * @return the number of bytes read and successfully written
     *
     * @throws IOException if an I/O error occurs when reading or writing
     */
    public static long copy(InputStream source, OutputStream target)
            throws IOException {
        LongAdder totalread = new LongAdder();
        copy(source, target, nread -> {
            totalread.add(nread);
            return true;
        });
        return totalread.sum();
    }

    /**
     * Reads all bytes from an input stream and writes them to an output stream.
     * While doing so, the given predicate is called with the amount of bytes
     * being read, to decide whenever they should be written to the output
     * stream. If the predicate returns <code>false</code> the copy operation is
     * stopped and no more data is written to the output stream.
     *
     * @param source the input stream to read from
     * @param target the path to the file
     * @param predicate the predicate tests if the copy operation should proceed
     *
     * @throws IOException if an I/O error occurs when reading or writing
     */
    public static void copy(InputStream source, OutputStream target,
            IntPredicate predicate) throws IOException {
        byte[] buf = new byte[BUFFER_SIZE];
        int n;
        while ((n = source.read(buf)) > 0 && predicate.test(n)) {
            target.write(buf, 0, n);
        }
    }

Cheers

Patrick


More information about the core-libs-dev mailing list