src/share/classes/java/nio/file/Files.java

Print this page
rev 7630 : 8019395: Consolidate StreamSupport.{stream,parallelStream} into a single method
Reviewed-by: henryjen
rev 7633 : 8017513: Support for closeable streams
Reviewed-by:
Contributed-by: brian.goetz@oracle.com


   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.nio.file;
  27 
  28 import java.nio.ByteBuffer;
  29 import java.nio.file.attribute.*;
  30 import java.nio.file.spi.FileSystemProvider;
  31 import java.nio.file.spi.FileTypeDetector;
  32 import java.nio.channels.FileChannel;
  33 import java.nio.channels.SeekableByteChannel;
  34 import java.io.Closeable;
  35 import java.io.InputStream;
  36 import java.io.OutputStream;
  37 import java.io.Reader;
  38 import java.io.Writer;
  39 import java.io.BufferedReader;
  40 import java.io.BufferedWriter;




  41 import java.io.InputStreamReader;

  42 import java.io.OutputStreamWriter;
  43 import java.io.IOException;
  44 import java.io.UncheckedIOException;
  45 import java.util.*;
  46 import java.util.function.BiPredicate;
  47 import java.util.stream.CloseableStream;
  48 import java.util.stream.DelegatingStream;
  49 import java.util.stream.Stream;
  50 import java.util.stream.StreamSupport;
  51 import java.security.AccessController;
  52 import java.security.PrivilegedAction;
  53 import java.nio.charset.Charset;
  54 import java.nio.charset.CharsetDecoder;
  55 import java.nio.charset.CharsetEncoder;

































  56 
  57 /**
  58  * This class consists exclusively of static methods that operate on files,
  59  * directories, or other types of files.
  60  *
  61  * <p> In most cases, the methods defined here will delegate to the associated
  62  * file system provider to perform the file operations.
  63  *
  64  * @since 1.7
  65  */
  66 
  67 public final class Files {
  68     private Files() { }
  69 
  70     /**
  71      * Returns the {@code FileSystemProvider} to delegate to.
  72      */
  73     private static FileSystemProvider provider(Path path) {
  74         return path.getFileSystem().provider();
  75     }
  76 















  77     // -- File contents --
  78 
  79     /**
  80      * Opens a file, returning an input stream to read from the file. The stream
  81      * will not be buffered, and is not required to support the {@link
  82      * InputStream#mark mark} or {@link InputStream#reset reset} methods. The
  83      * stream will be safe for access by multiple concurrent threads. Reading
  84      * commences at the beginning of the file. Whether the returned stream is
  85      * <i>asynchronously closeable</i> and/or <i>interruptible</i> is highly
  86      * file system provider specific and therefore not specified.
  87      *
  88      * <p> The {@code options} parameter determines how the file is opened.
  89      * If no options are present then it is equivalent to opening the file with
  90      * the {@link StandardOpenOption#READ READ} option. In addition to the {@code
  91      * READ} option, an implementation may also support additional implementation
  92      * specific options.
  93      *
  94      * @param   path
  95      *          the path to the file to open
  96      * @param   options


3164     public static Path write(Path path, Iterable<? extends CharSequence> lines,
3165                              Charset cs, OpenOption... options)
3166         throws IOException
3167     {
3168         // ensure lines is not null before opening file
3169         Objects.requireNonNull(lines);
3170         CharsetEncoder encoder = cs.newEncoder();
3171         OutputStream out = newOutputStream(path, options);
3172         try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, encoder))) {
3173             for (CharSequence line: lines) {
3174                 writer.append(line);
3175                 writer.newLine();
3176             }
3177         }
3178         return path;
3179     }
3180 
3181     // -- Stream APIs --
3182 
3183     /**
3184      * Implementation of CloseableStream
3185      */
3186     private static class DelegatingCloseableStream<T> extends DelegatingStream<T>
3187         implements CloseableStream<T>
3188     {
3189         private final Closeable closeable;
3190 
3191         DelegatingCloseableStream(Closeable c, Stream<T> delegate) {
3192             super(delegate);
3193             this.closeable = c;
3194         }
3195 
3196         public void close() {
3197             try {
3198                 closeable.close();
3199             } catch (IOException ex) {
3200                 throw new UncheckedIOException(ex);
3201             }
3202         }
3203     }
3204 
3205     /**
3206      * Return a lazily populated {@code CloseableStream}, the elements of
3207      * which are the entries in the directory.  The listing is not recursive.
3208      *
3209      * <p> The elements of the stream are {@link Path} objects that are
3210      * obtained as if by {@link Path#resolve(Path) resolving} the name of the
3211      * directory entry against {@code dir}. Some file systems maintain special
3212      * links to the directory itself and the directory's parent directory.
3213      * Entries representing these links are not included.
3214      *
3215      * <p> The stream is <i>weakly consistent</i>. It is thread safe but does
3216      * not freeze the directory while iterating, so it may (or may not)
3217      * reflect updates to the directory that occur after returning from this
3218      * method.
3219      *
3220      * <p> When not using the try-with-resources construct, then the stream's
3221      * {@link CloseableStream#close close} method should be invoked after the
3222      * operation is completed so as to free any resources held for the open
3223      * directory. Operating on a closed stream behaves as if the end of stream
3224      * has been reached. Due to read-ahead, one or more elements may be
3225      * returned after the stream has been closed.
3226      *
3227      * <p> If an {@link IOException} is thrown when accessing the directory
3228      * after this method has returned, it is wrapped in an {@link
3229      * UncheckedIOException} which will be thrown from the method that caused
3230      * the access to take place.
3231      *
3232      * @param   dir  The path to the directory
3233      *
3234      * @return  The {@code CloseableStream} describing the content of the
3235      *          directory
3236      *
3237      * @throws  NotDirectoryException
3238      *          if the file could not otherwise be opened because it is not
3239      *          a directory <i>(optional specific exception)</i>
3240      * @throws  IOException
3241      *          if an I/O error occurs when opening the directory
3242      * @throws  SecurityException
3243      *          In the case of the default provider, and a security manager is
3244      *          installed, the {@link SecurityManager#checkRead(String) checkRead}
3245      *          method is invoked to check read access to the directory.
3246      *
3247      * @see     #newDirectoryStream(Path)
3248      * @since   1.8
3249      */
3250     public static CloseableStream<Path> list(Path dir) throws IOException {

3251         DirectoryStream<Path> ds = Files.newDirectoryStream(dir);

3252         final Iterator<Path> delegate = ds.iterator();
3253 
3254         // Re-wrap DirectoryIteratorException to UncheckedIOException
3255         Iterator<Path> it = new Iterator<Path>() {
3256             public boolean hasNext() {
3257                 try {
3258                     return delegate.hasNext();
3259                 } catch (DirectoryIteratorException e) {
3260                     throw new UncheckedIOException(e.getCause());
3261                 }
3262             }
3263             public Path next() {
3264                 try {
3265                     return delegate.next();
3266                 } catch (DirectoryIteratorException e) {
3267                     throw new UncheckedIOException(e.getCause());
3268                 }
3269             }
3270         };
3271 
3272         Stream<Path> s = StreamSupport.stream(
3273                 Spliterators.spliteratorUnknownSize(it, Spliterator.DISTINCT),
3274                 false);
3275         return new DelegatingCloseableStream<>(ds, s);


3276     }
3277 
3278     /**
3279      * Return a {@code CloseableStream} that is lazily populated with {@code
3280      * Path} by walking the file tree rooted at a given starting file.  The
3281      * file tree is traversed <em>depth-first</em>, the elements in the stream
3282      * are {@link Path} objects that are obtained as if by {@link
3283      * Path#resolve(Path) resolving} the relative path against {@code start}.
3284      *
3285      * <p> The {@code stream} walks the file tree as elements are consumed.
3286      * The {@code CloseableStream} returned is guaranteed to have at least one
3287      * element, the starting file itself. For each file visited, the stream
3288      * attempts to read its {@link BasicFileAttributes}. If the file is a
3289      * directory and can be opened successfully, entries in the directory, and
3290      * their <em>descendants</em> will follow the directory in the stream as
3291      * they are encountered. When all entries have been visited, then the
3292      * directory is closed. The file tree walk then continues at the next
3293      * <em>sibling</em> of the directory.
3294      *
3295      * <p> The stream is <i>weakly consistent</i>. It does not freeze the
3296      * file tree while iterating, so it may (or may not) reflect updates to
3297      * the file tree that occur after returned from this method.
3298      *
3299      * <p> By default, symbolic links are not automatically followed by this
3300      * method. If the {@code options} parameter contains the {@link
3301      * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then symbolic links are
3302      * followed. When following links, and the attributes of the target cannot
3303      * be read, then this method attempts to get the {@code BasicFileAttributes}
3304      * of the link.
3305      *
3306      * <p> If the {@code options} parameter contains the {@link
3307      * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then the stream keeps
3308      * track of directories visited so that cycles can be detected. A cycle
3309      * arises when there is an entry in a directory that is an ancestor of the
3310      * directory. Cycle detection is done by recording the {@link
3311      * java.nio.file.attribute.BasicFileAttributes#fileKey file-key} of directories,
3312      * or if file keys are not available, by invoking the {@link #isSameFile
3313      * isSameFile} method to test if a directory is the same file as an
3314      * ancestor. When a cycle is detected it is treated as an I/O error with
3315      * an instance of {@link FileSystemLoopException}.
3316      *
3317      * <p> The {@code maxDepth} parameter is the maximum number of levels of
3318      * directories to visit. A value of {@code 0} means that only the starting
3319      * file is visited, unless denied by the security manager. A value of
3320      * {@link Integer#MAX_VALUE MAX_VALUE} may be used to indicate that all
3321      * levels should be visited.
3322      *
3323      * <p> When a security manager is installed and it denies access to a file
3324      * (or directory), then it is ignored and not included in the stream.
3325      *
3326      * <p> When not using the try-with-resources construct, then the stream's
3327      * {@link CloseableStream#close close} method should be invoked after the
3328      * operation is completed so as to free any resources held for the open
3329      * directory. Operate the stream after it is closed will throw an
3330      * {@link java.lang.IllegalStateException}.
3331      *
3332      * <p> If an {@link IOException} is thrown when accessing the directory
3333      * after this method has returned, it is wrapped in an {@link
3334      * UncheckedIOException} which will be thrown from the method that caused
3335      * the access to take place.
3336      *
3337      * @param   start
3338      *          the starting file
3339      * @param   maxDepth
3340      *          the maximum number of directory levels to visit
3341      * @param   options
3342      *          options to configure the traversal
3343      *
3344      * @return  the {@link CloseableStream} of {@link Path}
3345      *
3346      * @throws  IllegalArgumentException
3347      *          if the {@code maxDepth} parameter is negative
3348      * @throws  SecurityException
3349      *          If the security manager denies access to the starting file.
3350      *          In the case of the default provider, the {@link
3351      *          SecurityManager#checkRead(String) checkRead} method is invoked
3352      *          to check read access to the directory.
3353      * @throws  IOException
3354      *          if an I/O error is thrown when accessing the starting file.
3355      * @since   1.8
3356      */
3357     public static CloseableStream<Path> walk(Path start, int maxDepth,

3358                                              FileVisitOption... options)
3359         throws IOException
3360     {
3361         FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
3362 
3363         Stream<Path> s = StreamSupport.stream(
3364                 Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT),
3365                 false).
3366                 map(entry -> entry.file());
3367         return new DelegatingCloseableStream<>(iterator, s);


3368     }
3369 
3370     /**
3371      * Return a {@code CloseableStream} that is lazily populated with {@code
3372      * Path} by walking the file tree rooted at a given starting file.  The
3373      * file tree is traversed <em>depth-first</em>, the elements in the stream
3374      * are {@link Path} objects that are obtained as if by {@link
3375      * Path#resolve(Path) resolving} the relative path against {@code start}.
3376      *
3377      * <p> This method works as if invoking it were equivalent to evaluating the
3378      * expression:
3379      * <blockquote><pre>
3380      * walk(start, Integer.MAX_VALUE, options)
3381      * </pre></blockquote>
3382      * In other words, it visits all levels of the file tree.
3383      *
3384      * @param   start
3385      *          the starting file
3386      * @param   options
3387      *          options to configure the traversal
3388      *
3389      * @return  the {@link CloseableStream} of {@link Path}
3390      *
3391      * @throws  SecurityException
3392      *          If the security manager denies access to the starting file.
3393      *          In the case of the default provider, the {@link
3394      *          SecurityManager#checkRead(String) checkRead} method is invoked
3395      *          to check read access to the directory.
3396      * @throws  IOException
3397      *          if an I/O error is thrown when accessing the starting file.
3398      *
3399      * @see     #walk(Path, int, FileVisitOption...)
3400      * @since   1.8
3401      */
3402     public static CloseableStream<Path> walk(Path start,

3403                                              FileVisitOption... options)
3404         throws IOException
3405     {
3406         return walk(start, Integer.MAX_VALUE, options);
3407     }
3408 
3409     /**
3410      * Return a {@code CloseableStream} that is lazily populated with {@code
3411      * Path} by searching for files in a file tree rooted at a given starting
3412      * file.
3413      *
3414      * <p> This method walks the file tree in exactly the manner specified by
3415      * the {@link #walk walk} method. For each file encountered, the given
3416      * {@link BiPredicate} is invoked with its {@link Path} and {@link
3417      * BasicFileAttributes}. The {@code Path} object is obtained as if by
3418      * {@link Path#resolve(Path) resolving} the relative path against {@code
3419      * start} and is only included in the returned {@link CloseableStream} if
3420      * the {@code BiPredicate} returns true. Compare to calling {@link
3421      * java.util.stream.Stream#filter filter} on the {@code Stream}
3422      * returned by {@code walk} method, this method may be more efficient by
3423      * avoiding redundant retrieval of the {@code BasicFileAttributes}.
3424      *
3425      * <p> If an {@link IOException} is thrown when accessing the directory
3426      * after returned from this method, it is wrapped in an {@link
3427      * UncheckedIOException} which will be thrown from the method that caused
3428      * the access to take place.
3429      *
3430      * @param   start
3431      *          the starting file
3432      * @param   maxDepth
3433      *          the maximum number of directory levels to search
3434      * @param   matcher
3435      *          the function used to decide whether a file should be included
3436      *          in the returned stream
3437      * @param   options
3438      *          options to configure the traversal
3439      *
3440      * @return  the {@link CloseableStream} of {@link Path}
3441      *
3442      * @throws  IllegalArgumentException
3443      *          if the {@code maxDepth} parameter is negative
3444      * @throws  SecurityException
3445      *          If the security manager denies access to the starting file.
3446      *          In the case of the default provider, the {@link
3447      *          SecurityManager#checkRead(String) checkRead} method is invoked
3448      *          to check read access to the directory.
3449      * @throws  IOException
3450      *          if an I/O error is thrown when accessing the starting file.
3451      *
3452      * @see     #walk(Path, int, FileVisitOption...)
3453      * @since   1.8
3454      */
3455     public static CloseableStream<Path> find(Path start,

3456                                              int maxDepth,
3457                                              BiPredicate<Path, BasicFileAttributes> matcher,
3458                                              FileVisitOption... options)
3459         throws IOException
3460     {
3461         FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
3462 
3463         Stream<Path> s = StreamSupport.stream(
3464                 Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT),
3465                 false).
3466                 filter(entry -> matcher.test(entry.file(), entry.attributes())).
3467                 map(entry -> entry.file());
3468         return new DelegatingCloseableStream<>(iterator, s);


3469     }
3470 
3471     /**
3472      * Read all lines from a file as a {@code CloseableStream}.  Unlike {@link
3473      * #readAllLines(Path, Charset) readAllLines}, this method does not read
3474      * all lines into a {@code List}, but instead populates lazily as the stream
3475      * is consumed.
3476      *
3477      * <p> Bytes from the file are decoded into characters using the specified
3478      * charset and the same line terminators as specified by {@code
3479      * readAllLines} are supported.
3480      *
3481      * <p> After this method returns, then any subsequent I/O exception that
3482      * occurs while reading from the file or when a malformed or unmappable byte
3483      * sequence is read, is wrapped in an {@link UncheckedIOException} that will
3484      * be thrown form the
3485      * {@link java.util.stream.Stream} method that caused the read to take
3486      * place. In case an {@code IOException} is thrown when closing the file,
3487      * it is also wrapped as an {@code UncheckedIOException}.
3488      *
3489      * <p> When not using the try-with-resources construct, then stream's
3490      * {@link CloseableStream#close close} method should be invoked after
3491      * operation is completed so as to free any resources held for the open
3492      * file.
3493      *
3494      * @param   path
3495      *          the path to the file
3496      * @param   cs
3497      *          the charset to use for decoding
3498      *
3499      * @return  the lines from the file as a {@code CloseableStream}
3500      *
3501      * @throws  IOException
3502      *          if an I/O error occurs opening the file
3503      * @throws  SecurityException
3504      *          In the case of the default provider, and a security manager is
3505      *          installed, the {@link SecurityManager#checkRead(String) checkRead}
3506      *          method is invoked to check read access to the file.
3507      *
3508      * @see     #readAllLines(Path, Charset)
3509      * @see     #newBufferedReader(Path, Charset)
3510      * @see     java.io.BufferedReader#lines()
3511      * @since   1.8
3512      */
3513     public static CloseableStream<String> lines(Path path, Charset cs)
3514         throws IOException
3515     {
3516         BufferedReader br = Files.newBufferedReader(path, cs);
3517         return new DelegatingCloseableStream<>(br, br.lines());





3518     }
3519 }


   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.nio.file;
  27 











  28 import java.io.BufferedReader;
  29 import java.io.BufferedWriter;
  30 import java.io.Closeable;
  31 import java.io.File;
  32 import java.io.IOException;
  33 import java.io.InputStream;
  34 import java.io.InputStreamReader;
  35 import java.io.OutputStream;
  36 import java.io.OutputStreamWriter;
  37 import java.io.Reader;
  38 import java.io.UncheckedIOException;
  39 import java.io.Writer;
  40 import java.nio.ByteBuffer;
  41 import java.nio.channels.FileChannel;
  42 import java.nio.channels.SeekableByteChannel;




  43 import java.nio.charset.Charset;
  44 import java.nio.charset.CharsetDecoder;
  45 import java.nio.charset.CharsetEncoder;
  46 import java.nio.file.attribute.BasicFileAttributeView;
  47 import java.nio.file.attribute.BasicFileAttributes;
  48 import java.nio.file.attribute.DosFileAttributes;
  49 import java.nio.file.attribute.FileAttribute;
  50 import java.nio.file.attribute.FileAttributeView;
  51 import java.nio.file.attribute.FileOwnerAttributeView;
  52 import java.nio.file.attribute.FileStoreAttributeView;
  53 import java.nio.file.attribute.FileTime;
  54 import java.nio.file.attribute.PosixFileAttributeView;
  55 import java.nio.file.attribute.PosixFileAttributes;
  56 import java.nio.file.attribute.PosixFilePermission;
  57 import java.nio.file.attribute.UserPrincipal;
  58 import java.nio.file.spi.FileSystemProvider;
  59 import java.nio.file.spi.FileTypeDetector;
  60 import java.security.AccessController;
  61 import java.security.PrivilegedAction;
  62 import java.util.ArrayList;
  63 import java.util.Arrays;
  64 import java.util.Collections;
  65 import java.util.EnumSet;
  66 import java.util.HashSet;
  67 import java.util.Iterator;
  68 import java.util.List;
  69 import java.util.Map;
  70 import java.util.MayHoldCloseableResource;
  71 import java.util.Objects;
  72 import java.util.ServiceLoader;
  73 import java.util.Set;
  74 import java.util.Spliterator;
  75 import java.util.Spliterators;
  76 import java.util.function.BiPredicate;
  77 import java.util.stream.Stream;
  78 import java.util.stream.StreamSupport;
  79 
  80 /**
  81  * This class consists exclusively of static methods that operate on files,
  82  * directories, or other types of files.
  83  *
  84  * <p> In most cases, the methods defined here will delegate to the associated
  85  * file system provider to perform the file operations.
  86  *
  87  * @since 1.7
  88  */
  89 
  90 public final class Files {
  91     private Files() { }
  92 
  93     /**
  94      * Returns the {@code FileSystemProvider} to delegate to.
  95      */
  96     private static FileSystemProvider provider(Path path) {
  97         return path.getFileSystem().provider();
  98     }
  99 
 100     /**
 101      * Convert a Closeable to a Runnable by converting checked IOException
 102      * to UncheckedIOException
 103      */
 104     private static Runnable asUncheckedRunnable(Closeable c) {
 105         return () -> {
 106             try {
 107                 c.close();
 108             }
 109             catch (IOException e) {
 110                 throw new UncheckedIOException(e);
 111             }
 112         };
 113     }
 114 
 115     // -- File contents --
 116 
 117     /**
 118      * Opens a file, returning an input stream to read from the file. The stream
 119      * will not be buffered, and is not required to support the {@link
 120      * InputStream#mark mark} or {@link InputStream#reset reset} methods. The
 121      * stream will be safe for access by multiple concurrent threads. Reading
 122      * commences at the beginning of the file. Whether the returned stream is
 123      * <i>asynchronously closeable</i> and/or <i>interruptible</i> is highly
 124      * file system provider specific and therefore not specified.
 125      *
 126      * <p> The {@code options} parameter determines how the file is opened.
 127      * If no options are present then it is equivalent to opening the file with
 128      * the {@link StandardOpenOption#READ READ} option. In addition to the {@code
 129      * READ} option, an implementation may also support additional implementation
 130      * specific options.
 131      *
 132      * @param   path
 133      *          the path to the file to open
 134      * @param   options


3202     public static Path write(Path path, Iterable<? extends CharSequence> lines,
3203                              Charset cs, OpenOption... options)
3204         throws IOException
3205     {
3206         // ensure lines is not null before opening file
3207         Objects.requireNonNull(lines);
3208         CharsetEncoder encoder = cs.newEncoder();
3209         OutputStream out = newOutputStream(path, options);
3210         try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, encoder))) {
3211             for (CharSequence line: lines) {
3212                 writer.append(line);
3213                 writer.newLine();
3214             }
3215         }
3216         return path;
3217     }
3218 
3219     // -- Stream APIs --
3220 
3221     /**
3222      * Return a lazily populated {@code Stream}, the elements of






















3223      * which are the entries in the directory.  The listing is not recursive.
3224      *
3225      * <p> The elements of the stream are {@link Path} objects that are
3226      * obtained as if by {@link Path#resolve(Path) resolving} the name of the
3227      * directory entry against {@code dir}. Some file systems maintain special
3228      * links to the directory itself and the directory's parent directory.
3229      * Entries representing these links are not included.
3230      *
3231      * <p> The stream is <i>weakly consistent</i>. It is thread safe but does
3232      * not freeze the directory while iterating, so it may (or may not)
3233      * reflect updates to the directory that occur after returning from this
3234      * method.
3235      *
3236      * <p> When not using the try-with-resources construct, then the stream's
3237      * {@link Stream#close close} method should be invoked after the
3238      * operation is completed so as to free any resources held for the open
3239      * directory. Operating on a closed stream behaves as if the end of stream
3240      * has been reached. Due to read-ahead, one or more elements may be
3241      * returned after the stream has been closed.
3242      *
3243      * <p> If an {@link IOException} is thrown when accessing the directory
3244      * after this method has returned, it is wrapped in an {@link
3245      * UncheckedIOException} which will be thrown from the method that caused
3246      * the access to take place.
3247      *
3248      * @param   dir  The path to the directory
3249      *
3250      * @return  The {@code Stream} describing the content of the
3251      *          directory
3252      *
3253      * @throws  NotDirectoryException
3254      *          if the file could not otherwise be opened because it is not
3255      *          a directory <i>(optional specific exception)</i>
3256      * @throws  IOException
3257      *          if an I/O error occurs when opening the directory
3258      * @throws  SecurityException
3259      *          In the case of the default provider, and a security manager is
3260      *          installed, the {@link SecurityManager#checkRead(String) checkRead}
3261      *          method is invoked to check read access to the directory.
3262      *
3263      * @see     #newDirectoryStream(Path)
3264      * @since   1.8
3265      */
3266     @MayHoldCloseableResource.HoldsResource
3267     public static Stream<Path> list(Path dir) throws IOException {
3268         DirectoryStream<Path> ds = Files.newDirectoryStream(dir);
3269         try {
3270             final Iterator<Path> delegate = ds.iterator();
3271 
3272             // Re-wrap DirectoryIteratorException to UncheckedIOException
3273             Iterator<Path> it = new Iterator<Path>() {
3274                 public boolean hasNext() {
3275                     try {
3276                         return delegate.hasNext();
3277                     } catch (DirectoryIteratorException e) {
3278                         throw new UncheckedIOException(e.getCause());
3279                     }
3280                 }
3281                 public Path next() {
3282                     try {
3283                         return delegate.next();
3284                     } catch (DirectoryIteratorException e) {
3285                         throw new UncheckedIOException(e.getCause());
3286                     }
3287                 }
3288             };
3289 
3290             return StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, Spliterator.DISTINCT), false)
3291                                 .onClose(asUncheckedRunnable(ds));
3292         } catch (Error|RuntimeException e) {
3293             ds.close();
3294             throw e;
3295         }
3296     }
3297 
3298     /**
3299      * Return a {@code Stream} that is lazily populated with {@code
3300      * Path} by walking the file tree rooted at a given starting file.  The
3301      * file tree is traversed <em>depth-first</em>, the elements in the stream
3302      * are {@link Path} objects that are obtained as if by {@link
3303      * Path#resolve(Path) resolving} the relative path against {@code start}.
3304      *
3305      * <p> The {@code stream} walks the file tree as elements are consumed.
3306      * The {@code Stream} returned is guaranteed to have at least one
3307      * element, the starting file itself. For each file visited, the stream
3308      * attempts to read its {@link BasicFileAttributes}. If the file is a
3309      * directory and can be opened successfully, entries in the directory, and
3310      * their <em>descendants</em> will follow the directory in the stream as
3311      * they are encountered. When all entries have been visited, then the
3312      * directory is closed. The file tree walk then continues at the next
3313      * <em>sibling</em> of the directory.
3314      *
3315      * <p> The stream is <i>weakly consistent</i>. It does not freeze the
3316      * file tree while iterating, so it may (or may not) reflect updates to
3317      * the file tree that occur after returned from this method.
3318      *
3319      * <p> By default, symbolic links are not automatically followed by this
3320      * method. If the {@code options} parameter contains the {@link
3321      * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then symbolic links are
3322      * followed. When following links, and the attributes of the target cannot
3323      * be read, then this method attempts to get the {@code BasicFileAttributes}
3324      * of the link.
3325      *
3326      * <p> If the {@code options} parameter contains the {@link
3327      * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then the stream keeps
3328      * track of directories visited so that cycles can be detected. A cycle
3329      * arises when there is an entry in a directory that is an ancestor of the
3330      * directory. Cycle detection is done by recording the {@link
3331      * java.nio.file.attribute.BasicFileAttributes#fileKey file-key} of directories,
3332      * or if file keys are not available, by invoking the {@link #isSameFile
3333      * isSameFile} method to test if a directory is the same file as an
3334      * ancestor. When a cycle is detected it is treated as an I/O error with
3335      * an instance of {@link FileSystemLoopException}.
3336      *
3337      * <p> The {@code maxDepth} parameter is the maximum number of levels of
3338      * directories to visit. A value of {@code 0} means that only the starting
3339      * file is visited, unless denied by the security manager. A value of
3340      * {@link Integer#MAX_VALUE MAX_VALUE} may be used to indicate that all
3341      * levels should be visited.
3342      *
3343      * <p> When a security manager is installed and it denies access to a file
3344      * (or directory), then it is ignored and not included in the stream.
3345      *
3346      * <p> When not using the try-with-resources construct, then the stream's
3347      * {@link Stream#close close} method should be invoked after the
3348      * operation is completed so as to free any resources held for the open
3349      * directory. Operate the stream after it is closed will throw an
3350      * {@link java.lang.IllegalStateException}.
3351      *
3352      * <p> If an {@link IOException} is thrown when accessing the directory
3353      * after this method has returned, it is wrapped in an {@link
3354      * UncheckedIOException} which will be thrown from the method that caused
3355      * the access to take place.
3356      *
3357      * @param   start
3358      *          the starting file
3359      * @param   maxDepth
3360      *          the maximum number of directory levels to visit
3361      * @param   options
3362      *          options to configure the traversal
3363      *
3364      * @return  the {@link Stream} of {@link Path}
3365      *
3366      * @throws  IllegalArgumentException
3367      *          if the {@code maxDepth} parameter is negative
3368      * @throws  SecurityException
3369      *          If the security manager denies access to the starting file.
3370      *          In the case of the default provider, the {@link
3371      *          SecurityManager#checkRead(String) checkRead} method is invoked
3372      *          to check read access to the directory.
3373      * @throws  IOException
3374      *          if an I/O error is thrown when accessing the starting file.
3375      * @since   1.8
3376      */
3377     @MayHoldCloseableResource.HoldsResource
3378     public static Stream<Path> walk(Path start, int maxDepth,
3379                                     FileVisitOption... options)
3380             throws IOException {

3381         FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
3382         try {
3383             return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT), false)
3384                                 .onClose(iterator::close)
3385                                 .map(entry -> entry.file());
3386         } catch (Error|RuntimeException e) {
3387             iterator.close();
3388             throw e;
3389         }
3390     }
3391 
3392     /**
3393      * Return a {@code Stream} that is lazily populated with {@code
3394      * Path} by walking the file tree rooted at a given starting file.  The
3395      * file tree is traversed <em>depth-first</em>, the elements in the stream
3396      * are {@link Path} objects that are obtained as if by {@link
3397      * Path#resolve(Path) resolving} the relative path against {@code start}.
3398      *
3399      * <p> This method works as if invoking it were equivalent to evaluating the
3400      * expression:
3401      * <blockquote><pre>
3402      * walk(start, Integer.MAX_VALUE, options)
3403      * </pre></blockquote>
3404      * In other words, it visits all levels of the file tree.
3405      *
3406      * @param   start
3407      *          the starting file
3408      * @param   options
3409      *          options to configure the traversal
3410      *
3411      * @return  the {@link Stream} of {@link Path}
3412      *
3413      * @throws  SecurityException
3414      *          If the security manager denies access to the starting file.
3415      *          In the case of the default provider, the {@link
3416      *          SecurityManager#checkRead(String) checkRead} method is invoked
3417      *          to check read access to the directory.
3418      * @throws  IOException
3419      *          if an I/O error is thrown when accessing the starting file.
3420      *
3421      * @see     #walk(Path, int, FileVisitOption...)
3422      * @since   1.8
3423      */
3424     @MayHoldCloseableResource.HoldsResource
3425     public static Stream<Path> walk(Path start,
3426                                     FileVisitOption... options)
3427             throws IOException {

3428         return walk(start, Integer.MAX_VALUE, options);
3429     }
3430 
3431     /**
3432      * Return a {@code Stream} that is lazily populated with {@code
3433      * Path} by searching for files in a file tree rooted at a given starting
3434      * file.
3435      *
3436      * <p> This method walks the file tree in exactly the manner specified by
3437      * the {@link #walk walk} method. For each file encountered, the given
3438      * {@link BiPredicate} is invoked with its {@link Path} and {@link
3439      * BasicFileAttributes}. The {@code Path} object is obtained as if by
3440      * {@link Path#resolve(Path) resolving} the relative path against {@code
3441      * start} and is only included in the returned {@link Stream} if
3442      * the {@code BiPredicate} returns true. Compare to calling {@link
3443      * java.util.stream.Stream#filter filter} on the {@code Stream}
3444      * returned by {@code walk} method, this method may be more efficient by
3445      * avoiding redundant retrieval of the {@code BasicFileAttributes}.
3446      *
3447      * <p> If an {@link IOException} is thrown when accessing the directory
3448      * after returned from this method, it is wrapped in an {@link
3449      * UncheckedIOException} which will be thrown from the method that caused
3450      * the access to take place.
3451      *
3452      * @param   start
3453      *          the starting file
3454      * @param   maxDepth
3455      *          the maximum number of directory levels to search
3456      * @param   matcher
3457      *          the function used to decide whether a file should be included
3458      *          in the returned stream
3459      * @param   options
3460      *          options to configure the traversal
3461      *
3462      * @return  the {@link Stream} of {@link Path}
3463      *
3464      * @throws  IllegalArgumentException
3465      *          if the {@code maxDepth} parameter is negative
3466      * @throws  SecurityException
3467      *          If the security manager denies access to the starting file.
3468      *          In the case of the default provider, the {@link
3469      *          SecurityManager#checkRead(String) checkRead} method is invoked
3470      *          to check read access to the directory.
3471      * @throws  IOException
3472      *          if an I/O error is thrown when accessing the starting file.
3473      *
3474      * @see     #walk(Path, int, FileVisitOption...)
3475      * @since   1.8
3476      */
3477     @MayHoldCloseableResource.HoldsResource
3478     public static Stream<Path> find(Path start,
3479                                     int maxDepth,
3480                                     BiPredicate<Path, BasicFileAttributes> matcher,
3481                                     FileVisitOption... options)
3482             throws IOException {

3483         FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
3484         try {
3485             return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT), false)
3486                                 .onClose(iterator::close)
3487                                 .filter(entry -> matcher.test(entry.file(), entry.attributes()))
3488                                 .map(entry -> entry.file());
3489         } catch (Error|RuntimeException e) {
3490             iterator.close();
3491             throw e;
3492         }
3493     }
3494 
3495     /**
3496      * Read all lines from a file as a {@code Stream}.  Unlike {@link
3497      * #readAllLines(Path, Charset) readAllLines}, this method does not read
3498      * all lines into a {@code List}, but instead populates lazily as the stream
3499      * is consumed.
3500      *
3501      * <p> Bytes from the file are decoded into characters using the specified
3502      * charset and the same line terminators as specified by {@code
3503      * readAllLines} are supported.
3504      *
3505      * <p> After this method returns, then any subsequent I/O exception that
3506      * occurs while reading from the file or when a malformed or unmappable byte
3507      * sequence is read, is wrapped in an {@link UncheckedIOException} that will
3508      * be thrown form the
3509      * {@link java.util.stream.Stream} method that caused the read to take
3510      * place. In case an {@code IOException} is thrown when closing the file,
3511      * it is also wrapped as an {@code UncheckedIOException}.
3512      *
3513      * <p> When not using the try-with-resources construct, then stream's
3514      * {@link Stream#close close} method should be invoked after
3515      * operation is completed so as to free any resources held for the open
3516      * file.
3517      *
3518      * @param   path
3519      *          the path to the file
3520      * @param   cs
3521      *          the charset to use for decoding
3522      *
3523      * @return  the lines from the file as a {@code Stream}
3524      *
3525      * @throws  IOException
3526      *          if an I/O error occurs opening the file
3527      * @throws  SecurityException
3528      *          In the case of the default provider, and a security manager is
3529      *          installed, the {@link SecurityManager#checkRead(String) checkRead}
3530      *          method is invoked to check read access to the file.
3531      *
3532      * @see     #readAllLines(Path, Charset)
3533      * @see     #newBufferedReader(Path, Charset)
3534      * @see     java.io.BufferedReader#lines()
3535      * @since   1.8
3536      */
3537     @MayHoldCloseableResource.HoldsResource
3538     public static Stream<String> lines(Path path, Charset cs) throws IOException {

3539         BufferedReader br = Files.newBufferedReader(path, cs);
3540         try {
3541             return br.lines().onClose(asUncheckedRunnable(br));
3542         } catch (Error|RuntimeException e) {
3543             br.close();
3544             throw e;
3545         }
3546     }
3547 }