jdk/src/share/classes/java/nio/file/Files.java
changeset 17696 23a863fbb6c3
parent 17170 9f33b89c7978
child 17728 8bbdf55ba9d4
equal deleted inserted replaced
17695:032254f2467b 17696:23a863fbb6c3
    27 
    27 
    28 import java.nio.file.attribute.*;
    28 import java.nio.file.attribute.*;
    29 import java.nio.file.spi.FileSystemProvider;
    29 import java.nio.file.spi.FileSystemProvider;
    30 import java.nio.file.spi.FileTypeDetector;
    30 import java.nio.file.spi.FileTypeDetector;
    31 import java.nio.channels.SeekableByteChannel;
    31 import java.nio.channels.SeekableByteChannel;
       
    32 import java.io.Closeable;
    32 import java.io.InputStream;
    33 import java.io.InputStream;
    33 import java.io.OutputStream;
    34 import java.io.OutputStream;
    34 import java.io.Reader;
    35 import java.io.Reader;
    35 import java.io.Writer;
    36 import java.io.Writer;
    36 import java.io.BufferedReader;
    37 import java.io.BufferedReader;
    37 import java.io.BufferedWriter;
    38 import java.io.BufferedWriter;
    38 import java.io.InputStreamReader;
    39 import java.io.InputStreamReader;
    39 import java.io.OutputStreamWriter;
    40 import java.io.OutputStreamWriter;
    40 import java.io.IOException;
    41 import java.io.IOException;
       
    42 import java.io.UncheckedIOException;
    41 import java.util.*;
    43 import java.util.*;
       
    44 import java.util.function.BiPredicate;
       
    45 import java.util.stream.CloseableStream;
       
    46 import java.util.stream.DelegatingStream;
       
    47 import java.util.stream.Stream;
       
    48 import java.util.stream.StreamSupport;
    42 import java.security.AccessController;
    49 import java.security.AccessController;
    43 import java.security.PrivilegedAction;
    50 import java.security.PrivilegedAction;
    44 import java.nio.charset.Charset;
    51 import java.nio.charset.Charset;
    45 import java.nio.charset.CharsetDecoder;
    52 import java.nio.charset.CharsetDecoder;
    46 import java.nio.charset.CharsetEncoder;
    53 import java.nio.charset.CharsetEncoder;
  2585                                     Set<FileVisitOption> options,
  2592                                     Set<FileVisitOption> options,
  2586                                     int maxDepth,
  2593                                     int maxDepth,
  2587                                     FileVisitor<? super Path> visitor)
  2594                                     FileVisitor<? super Path> visitor)
  2588         throws IOException
  2595         throws IOException
  2589     {
  2596     {
  2590         if (maxDepth < 0)
       
  2591             throw new IllegalArgumentException("'maxDepth' is negative");
       
  2592 
       
  2593         /**
  2597         /**
  2594          * Create a FileTreeWalker to walk the file tree, invoking the visitor
  2598          * Create a FileTreeWalker to walk the file tree, invoking the visitor
  2595          * for each event.
  2599          * for each event.
  2596          */
  2600          */
  2597         try (FileTreeWalker walker = new FileTreeWalker(options, maxDepth)) {
  2601         try (FileTreeWalker walker = new FileTreeWalker(options, maxDepth)) {
  3175                 writer.newLine();
  3179                 writer.newLine();
  3176             }
  3180             }
  3177         }
  3181         }
  3178         return path;
  3182         return path;
  3179     }
  3183     }
       
  3184 
       
  3185     // -- Stream APIs --
       
  3186 
       
  3187     /**
       
  3188      * Implementation of CloseableStream
       
  3189      */
       
  3190     private static class DelegatingCloseableStream<T> extends DelegatingStream<T>
       
  3191         implements CloseableStream<T>
       
  3192     {
       
  3193         private final Closeable closeable;
       
  3194 
       
  3195         DelegatingCloseableStream(Closeable c, Stream<T> delegate) {
       
  3196             super(delegate);
       
  3197             this.closeable = c;
       
  3198         }
       
  3199 
       
  3200         public void close() {
       
  3201             try {
       
  3202                 closeable.close();
       
  3203             } catch (IOException ex) {
       
  3204                 throw new UncheckedIOException(ex);
       
  3205             }
       
  3206         }
       
  3207     }
       
  3208 
       
  3209     /**
       
  3210      * Return a lazily populated {@code CloseableStream}, the elements of
       
  3211      * which are the entries in the directory.  The listing is not recursive.
       
  3212      *
       
  3213      * <p> The elements of the stream are {@link Path} objects that are
       
  3214      * obtained as if by {@link Path#resolve(Path) resolving} the name of the
       
  3215      * directory entry against {@code dir}. Some file systems maintain special
       
  3216      * links to the directory itself and the directory's parent directory.
       
  3217      * Entries representing these links are not included.
       
  3218      *
       
  3219      * <p> The stream is <i>weakly consistent</i>. It is thread safe but does
       
  3220      * not freeze the directory while iterating, so it may (or may not)
       
  3221      * reflect updates to the directory that occur after returning from this
       
  3222      * method.
       
  3223      *
       
  3224      * <p> When not using the try-with-resources construct, then the stream's
       
  3225      * {@link CloseableStream#close close} method should be invoked after the
       
  3226      * operation is completed so as to free any resources held for the open
       
  3227      * directory. Operating on a closed stream behaves as if the end of stream
       
  3228      * has been reached. Due to read-ahead, one or more elements may be
       
  3229      * returned after the stream has been closed.
       
  3230      *
       
  3231      * <p> If an {@link IOException} is thrown when accessing the directory
       
  3232      * after this method has returned, it is wrapped in an {@link
       
  3233      * UncheckedIOException} which will be thrown from the method that caused
       
  3234      * the access to take place.
       
  3235      *
       
  3236      * @param   dir  The path to the directory
       
  3237      *
       
  3238      * @return  The {@code CloseableStream} describing the content of the
       
  3239      *          directory
       
  3240      *
       
  3241      * @throws  NotDirectoryException
       
  3242      *          if the file could not otherwise be opened because it is not
       
  3243      *          a directory <i>(optional specific exception)</i>
       
  3244      * @throws  IOException
       
  3245      *          if an I/O error occurs when opening the directory
       
  3246      * @throws  SecurityException
       
  3247      *          In the case of the default provider, and a security manager is
       
  3248      *          installed, the {@link SecurityManager#checkRead(String) checkRead}
       
  3249      *          method is invoked to check read access to the directory.
       
  3250      *
       
  3251      * @see     #newDirectoryStream(Path)
       
  3252      * @since   1.8
       
  3253      */
       
  3254     public static CloseableStream<Path> list(Path dir) throws IOException {
       
  3255         DirectoryStream<Path> ds = Files.newDirectoryStream(dir);
       
  3256         final Iterator<Path> delegate = ds.iterator();
       
  3257 
       
  3258         // Re-wrap DirectoryIteratorException to UncheckedIOException
       
  3259         Iterator<Path> it = new Iterator<Path>() {
       
  3260             public boolean hasNext() {
       
  3261                 try {
       
  3262                     return delegate.hasNext();
       
  3263                 } catch (DirectoryIteratorException e) {
       
  3264                     throw new UncheckedIOException(e.getCause());
       
  3265                 }
       
  3266             }
       
  3267             public Path next() {
       
  3268                 try {
       
  3269                     return delegate.next();
       
  3270                 } catch (DirectoryIteratorException e) {
       
  3271                     throw new UncheckedIOException(e.getCause());
       
  3272                 }
       
  3273             }
       
  3274         };
       
  3275 
       
  3276         return new DelegatingCloseableStream<>(ds,
       
  3277             StreamSupport.stream(Spliterators.spliteratorUnknownSize(it,
       
  3278                                                                      Spliterator.DISTINCT)));
       
  3279     }
       
  3280 
       
  3281     /**
       
  3282      * Return a {@code CloseableStream} that is lazily populated with {@code
       
  3283      * Path} by walking the file tree rooted at a given starting file.  The
       
  3284      * file tree is traversed <em>depth-first</em>, the elements in the stream
       
  3285      * are {@link Path} objects that are obtained as if by {@link
       
  3286      * Path#resolve(Path) resolving} the relative path against {@code start}.
       
  3287      *
       
  3288      * <p> The {@code stream} walks the file tree as elements are consumed.
       
  3289      * The {@code CloseableStream} returned is guaranteed to have at least one
       
  3290      * element, the starting file itself. For each file visited, the stream
       
  3291      * attempts to read its {@link BasicFileAttributes}. If the file is a
       
  3292      * directory and can be opened successfully, entries in the directory, and
       
  3293      * their <em>descendants</em> will follow the directory in the stream as
       
  3294      * they are encountered. When all entries have been visited, then the
       
  3295      * directory is closed. The file tree walk then continues at the next
       
  3296      * <em>sibling</em> of the directory.
       
  3297      *
       
  3298      * <p> The stream is <i>weakly consistent</i>. It does not freeze the
       
  3299      * file tree while iterating, so it may (or may not) reflect updates to
       
  3300      * the file tree that occur after returned from this method.
       
  3301      *
       
  3302      * <p> By default, symbolic links are not automatically followed by this
       
  3303      * method. If the {@code options} parameter contains the {@link
       
  3304      * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then symbolic links are
       
  3305      * followed. When following links, and the attributes of the target cannot
       
  3306      * be read, then this method attempts to get the {@code BasicFileAttributes}
       
  3307      * of the link.
       
  3308      *
       
  3309      * <p> If the {@code options} parameter contains the {@link
       
  3310      * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then the stream keeps
       
  3311      * track of directories visited so that cycles can be detected. A cycle
       
  3312      * arises when there is an entry in a directory that is an ancestor of the
       
  3313      * directory. Cycle detection is done by recording the {@link
       
  3314      * java.nio.file.attribute.BasicFileAttributes#fileKey file-key} of directories,
       
  3315      * or if file keys are not available, by invoking the {@link #isSameFile
       
  3316      * isSameFile} method to test if a directory is the same file as an
       
  3317      * ancestor. When a cycle is detected it is treated as an I/O error with
       
  3318      * an instance of {@link FileSystemLoopException}.
       
  3319      *
       
  3320      * <p> The {@code maxDepth} parameter is the maximum number of levels of
       
  3321      * directories to visit. A value of {@code 0} means that only the starting
       
  3322      * file is visited, unless denied by the security manager. A value of
       
  3323      * {@link Integer#MAX_VALUE MAX_VALUE} may be used to indicate that all
       
  3324      * levels should be visited.
       
  3325      *
       
  3326      * <p> When a security manager is installed and it denies access to a file
       
  3327      * (or directory), then it is ignored and not included in the stream.
       
  3328      *
       
  3329      * <p> When not using the try-with-resources construct, then the stream's
       
  3330      * {@link CloseableStream#close close} method should be invoked after the
       
  3331      * operation is completed so as to free any resources held for the open
       
  3332      * directory. Operate the stream after it is closed will throw an
       
  3333      * {@link java.lang.IllegalStateException}.
       
  3334      *
       
  3335      * <p> If an {@link IOException} is thrown when accessing the directory
       
  3336      * after this method has returned, it is wrapped in an {@link
       
  3337      * UncheckedIOException} which will be thrown from the method that caused
       
  3338      * the access to take place.
       
  3339      *
       
  3340      * @param   start
       
  3341      *          the starting file
       
  3342      * @param   maxDepth
       
  3343      *          the maximum number of directory levels to visit
       
  3344      * @param   options
       
  3345      *          options to configure the traversal
       
  3346      *
       
  3347      * @return  the {@link CloseableStream} of {@link Path}
       
  3348      *
       
  3349      * @throws  IllegalArgumentException
       
  3350      *          if the {@code maxDepth} parameter is negative
       
  3351      * @throws  SecurityException
       
  3352      *          If the security manager denies access to the starting file.
       
  3353      *          In the case of the default provider, the {@link
       
  3354      *          SecurityManager#checkRead(String) checkRead} method is invoked
       
  3355      *          to check read access to the directory.
       
  3356      * @throws  IOException
       
  3357      *          if an I/O error is thrown when accessing the starting file.
       
  3358      * @since   1.8
       
  3359      */
       
  3360     public static CloseableStream<Path> walk(Path start, int maxDepth,
       
  3361                                              FileVisitOption... options)
       
  3362         throws IOException
       
  3363     {
       
  3364         FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
       
  3365         return new DelegatingCloseableStream<>(iterator,
       
  3366             StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT))
       
  3367                    .map(entry -> entry.file()));
       
  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         return new DelegatingCloseableStream<>(iterator,
       
  3463             StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT))
       
  3464                    .filter(entry -> matcher.test(entry.file(), entry.attributes()))
       
  3465                    .map(entry -> entry.file()));
       
  3466     }
       
  3467 
       
  3468     /**
       
  3469      * Read all lines from a file as a {@code CloseableStream}.  Unlike {@link
       
  3470      * #readAllLines(Path, Charset) readAllLines}, this method does not read
       
  3471      * all lines into a {@code List}, but instead populates lazily as the stream
       
  3472      * is consumed.
       
  3473      *
       
  3474      * <p> Bytes from the file are decoded into characters using the specified
       
  3475      * charset and the same line terminators as specified by {@code
       
  3476      * readAllLines} are supported.
       
  3477      *
       
  3478      * <p> After this method returns, then any subsequent I/O exception that
       
  3479      * occurs while reading from the file or when a malformed or unmappable byte
       
  3480      * sequence is read, is wrapped in an {@link UncheckedIOException} that will
       
  3481      * be thrown form the
       
  3482      * {@link java.util.stream.Stream} method that caused the read to take
       
  3483      * place. In case an {@code IOException} is thrown when closing the file,
       
  3484      * it is also wrapped as an {@code UncheckedIOException}.
       
  3485      *
       
  3486      * <p> When not using the try-with-resources construct, then stream's
       
  3487      * {@link CloseableStream#close close} method should be invoked after
       
  3488      * operation is completed so as to free any resources held for the open
       
  3489      * file.
       
  3490      *
       
  3491      * @param   path
       
  3492      *          the path to the file
       
  3493      * @param   cs
       
  3494      *          the charset to use for decoding
       
  3495      *
       
  3496      * @return  the lines from the file as a {@code CloseableStream}
       
  3497      *
       
  3498      * @throws  IOException
       
  3499      *          if an I/O error occurs opening the file
       
  3500      * @throws  SecurityException
       
  3501      *          In the case of the default provider, and a security manager is
       
  3502      *          installed, the {@link SecurityManager#checkRead(String) checkRead}
       
  3503      *          method is invoked to check read access to the file.
       
  3504      *
       
  3505      * @see     #readAllLines(Path, Charset)
       
  3506      * @see     #newBufferedReader(Path, Charset)
       
  3507      * @see     java.io.BufferedReader#lines()
       
  3508      * @since   1.8
       
  3509      */
       
  3510     public static CloseableStream<String> lines(Path path, Charset cs)
       
  3511         throws IOException
       
  3512     {
       
  3513         BufferedReader br = Files.newBufferedReader(path, cs);
       
  3514         return new DelegatingCloseableStream<>(br, br.lines());
       
  3515     }
  3180 }
  3516 }