Write Stream<String> to a file?

Paul Sandoz paul.sandoz at oracle.com
Wed Nov 20 02:44:18 PST 2013

On Nov 20, 2013, at 4:27 AM, Sam Pullara <spullara at gmail.com> wrote:

> My solution seems the right way to go and is basically a mirror of that method. It should probably have an override that takes a stream rather than just an Iterable to make it more obvious. Here is the form with all the static imports:
>    Stream<String> s = Files.lines(get(from), UTF_8);

>    Files.write(get(to), s::iterator, UTF_8);

We recently added some more methods to avoid passing in the charset for UTF-8, so you can do this:

   Stream<String> s = Files.lines(get(from));
   Files.write(get(to), s::iterator);

Ideally we should have a Files.write accepting a Stream<? extends CharSequence> and use forEachOrdered:

    public static Path write(Path path, Stream<? extends CharSequence> lines,
                             Charset cs, OpenOption... options)
        throws IOException
        // ensure lines is not null before opening file
        CharsetEncoder encoder = cs.newEncoder();
        OutputStream out = newOutputStream(path, options);
        try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, encoder))) {
            lines.forEachOrdered(line -> {
                writer.newLine();  // @@@ need to manage the annoying checked exception issue
        return path;

Then we can do a particularly inefficient file copy :-)

  Files.write(get(to), Files.lines(get(from)));

For parallel streams forEachOrdered will ensure there is no concurrent execution of the Consumer but that execution may still occur on different threads to that of the calling thread, which in this context i presume is OK. There is also the potential for OOME if the writing is slower than the reading + stream ops, since forEachOrdered will buffer elements that are ahead of elements yet to be reported.


More information about the lambda-dev mailing list