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.file.attribute.*;
29 import java.nio.file.spi.FileSystemProvider;
30 import java.nio.file.spi.FileTypeDetector;
31 import java.nio.channels.Channels;
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
3211 public static Path write(Path path, Iterable<? extends CharSequence> lines,
3212 Charset cs, OpenOption... options)
3213 throws IOException
3214 {
3215 // ensure lines is not null before opening file
3216 Objects.requireNonNull(lines);
3217 CharsetEncoder encoder = cs.newEncoder();
3218 OutputStream out = newOutputStream(path, options);
3219 try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, encoder))) {
3220 for (CharSequence line: lines) {
3221 writer.append(line);
3222 writer.newLine();
3223 }
3224 }
3225 return path;
3226 }
3227
3228 // -- Stream APIs --
3229
3230 /**
3231 * Implementation of CloseableStream
3232 */
3233 private static class DelegatingCloseableStream<T> extends DelegatingStream<T>
3234 implements CloseableStream<T>
3235 {
3236 private final Closeable closeable;
3237
3238 DelegatingCloseableStream(Closeable c, Stream<T> delegate) {
3239 super(delegate);
3240 this.closeable = c;
3241 }
3242
3243 public void close() {
3244 try {
3245 closeable.close();
3246 } catch (IOException ex) {
3247 throw new UncheckedIOException(ex);
3248 }
3249 }
3250 }
3251
3252 /**
3253 * Return a lazily populated {@code CloseableStream}, the elements of
3254 * which are the entries in the directory. The listing is not recursive.
3255 *
3256 * <p> The elements of the stream are {@link Path} objects that are
3257 * obtained as if by {@link Path#resolve(Path) resolving} the name of the
3258 * directory entry against {@code dir}. Some file systems maintain special
3259 * links to the directory itself and the directory's parent directory.
3260 * Entries representing these links are not included.
3261 *
3262 * <p> The stream is <i>weakly consistent</i>. It is thread safe but does
3263 * not freeze the directory while iterating, so it may (or may not)
3264 * reflect updates to the directory that occur after returning from this
3265 * method.
3266 *
3267 * <p> When not using the try-with-resources construct, then the stream's
3268 * {@link CloseableStream#close close} method should be invoked after the
3269 * operation is completed so as to free any resources held for the open
3270 * directory. Operating on a closed stream behaves as if the end of stream
3271 * has been reached. Due to read-ahead, one or more elements may be
3272 * returned after the stream has been closed.
3273 *
3274 * <p> If an {@link IOException} is thrown when accessing the directory
3275 * after this method has returned, it is wrapped in an {@link
3276 * UncheckedIOException} which will be thrown from the method that caused
3277 * the access to take place.
3278 *
3279 * @param dir The path to the directory
3280 *
3281 * @return The {@code CloseableStream} describing the content of the
3282 * directory
3283 *
3284 * @throws NotDirectoryException
3285 * if the file could not otherwise be opened because it is not
3286 * a directory <i>(optional specific exception)</i>
3287 * @throws IOException
3288 * if an I/O error occurs when opening the directory
3289 * @throws SecurityException
3290 * In the case of the default provider, and a security manager is
3291 * installed, the {@link SecurityManager#checkRead(String) checkRead}
3292 * method is invoked to check read access to the directory.
3293 *
3294 * @see #newDirectoryStream(Path)
3295 * @since 1.8
3296 */
3297 public static CloseableStream<Path> list(Path dir) throws IOException {
3298 DirectoryStream<Path> ds = Files.newDirectoryStream(dir);
3299 final Iterator<Path> delegate = ds.iterator();
3300
3301 // Re-wrap DirectoryIteratorException to UncheckedIOException
3302 Iterator<Path> it = new Iterator<Path>() {
3303 public boolean hasNext() {
3304 try {
3305 return delegate.hasNext();
3306 } catch (DirectoryIteratorException e) {
3307 throw new UncheckedIOException(e.getCause());
3308 }
3309 }
3310 public Path next() {
3311 try {
3312 return delegate.next();
3313 } catch (DirectoryIteratorException e) {
3314 throw new UncheckedIOException(e.getCause());
3315 }
3316 }
3317 };
3318
3319 Stream<Path> s = StreamSupport.stream(
3320 Spliterators.spliteratorUnknownSize(it, Spliterator.DISTINCT),
3321 false);
3322 return new DelegatingCloseableStream<>(ds, s);
3323 }
3324
3325 /**
3326 * Return a {@code CloseableStream} that is lazily populated with {@code
3327 * Path} by walking the file tree rooted at a given starting file. The
3328 * file tree is traversed <em>depth-first</em>, the elements in the stream
3329 * are {@link Path} objects that are obtained as if by {@link
3330 * Path#resolve(Path) resolving} the relative path against {@code start}.
3331 *
3332 * <p> The {@code stream} walks the file tree as elements are consumed.
3333 * The {@code CloseableStream} returned is guaranteed to have at least one
3334 * element, the starting file itself. For each file visited, the stream
3335 * attempts to read its {@link BasicFileAttributes}. If the file is a
3336 * directory and can be opened successfully, entries in the directory, and
3337 * their <em>descendants</em> will follow the directory in the stream as
3338 * they are encountered. When all entries have been visited, then the
3339 * directory is closed. The file tree walk then continues at the next
3340 * <em>sibling</em> of the directory.
3341 *
3342 * <p> The stream is <i>weakly consistent</i>. It does not freeze the
3343 * file tree while iterating, so it may (or may not) reflect updates to
3344 * the file tree that occur after returned from this method.
3345 *
3346 * <p> By default, symbolic links are not automatically followed by this
3347 * method. If the {@code options} parameter contains the {@link
3348 * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then symbolic links are
3349 * followed. When following links, and the attributes of the target cannot
3350 * be read, then this method attempts to get the {@code BasicFileAttributes}
3351 * of the link.
3352 *
3353 * <p> If the {@code options} parameter contains the {@link
3354 * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then the stream keeps
3355 * track of directories visited so that cycles can be detected. A cycle
3356 * arises when there is an entry in a directory that is an ancestor of the
3357 * directory. Cycle detection is done by recording the {@link
3358 * java.nio.file.attribute.BasicFileAttributes#fileKey file-key} of directories,
3359 * or if file keys are not available, by invoking the {@link #isSameFile
3360 * isSameFile} method to test if a directory is the same file as an
3361 * ancestor. When a cycle is detected it is treated as an I/O error with
3362 * an instance of {@link FileSystemLoopException}.
3363 *
3364 * <p> The {@code maxDepth} parameter is the maximum number of levels of
3365 * directories to visit. A value of {@code 0} means that only the starting
3366 * file is visited, unless denied by the security manager. A value of
3367 * {@link Integer#MAX_VALUE MAX_VALUE} may be used to indicate that all
3368 * levels should be visited.
3369 *
3370 * <p> When a security manager is installed and it denies access to a file
3371 * (or directory), then it is ignored and not included in the stream.
3372 *
3373 * <p> When not using the try-with-resources construct, then the stream's
3374 * {@link CloseableStream#close close} method should be invoked after the
3375 * operation is completed so as to free any resources held for the open
3376 * directory. Operate the stream after it is closed will throw an
3377 * {@link java.lang.IllegalStateException}.
3378 *
3379 * <p> If an {@link IOException} is thrown when accessing the directory
3380 * after this method has returned, it is wrapped in an {@link
3381 * UncheckedIOException} which will be thrown from the method that caused
3382 * the access to take place.
3383 *
3384 * @param start
3385 * the starting file
3386 * @param maxDepth
3387 * the maximum number of directory levels to visit
3388 * @param options
3389 * options to configure the traversal
3390 *
3391 * @return the {@link CloseableStream} of {@link Path}
3392 *
3393 * @throws IllegalArgumentException
3394 * if the {@code maxDepth} parameter is negative
3395 * @throws SecurityException
3396 * If the security manager denies access to the starting file.
3397 * In the case of the default provider, the {@link
3398 * SecurityManager#checkRead(String) checkRead} method is invoked
3399 * to check read access to the directory.
3400 * @throws IOException
3401 * if an I/O error is thrown when accessing the starting file.
3402 * @since 1.8
3403 */
3404 public static CloseableStream<Path> walk(Path start, int maxDepth,
3405 FileVisitOption... options)
3406 throws IOException
3407 {
3408 FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
3409
3410 Stream<Path> s = StreamSupport.stream(
3411 Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT),
3412 false).
3413 map(entry -> entry.file());
3414 return new DelegatingCloseableStream<>(iterator, s);
3415 }
3416
3417 /**
3418 * Return a {@code CloseableStream} that is lazily populated with {@code
3419 * Path} by walking the file tree rooted at a given starting file. The
3420 * file tree is traversed <em>depth-first</em>, the elements in the stream
3421 * are {@link Path} objects that are obtained as if by {@link
3422 * Path#resolve(Path) resolving} the relative path against {@code start}.
3423 *
3424 * <p> This method works as if invoking it were equivalent to evaluating the
3425 * expression:
3426 * <blockquote><pre>
3427 * walk(start, Integer.MAX_VALUE, options)
3428 * </pre></blockquote>
3429 * In other words, it visits all levels of the file tree.
3430 *
3431 * @param start
3432 * the starting file
3433 * @param options
3434 * options to configure the traversal
3435 *
3436 * @return the {@link CloseableStream} of {@link Path}
3437 *
3438 * @throws SecurityException
3439 * If the security manager denies access to the starting file.
3440 * In the case of the default provider, the {@link
3441 * SecurityManager#checkRead(String) checkRead} method is invoked
3442 * to check read access to the directory.
3443 * @throws IOException
3444 * if an I/O error is thrown when accessing the starting file.
3445 *
3446 * @see #walk(Path, int, FileVisitOption...)
3447 * @since 1.8
3448 */
3449 public static CloseableStream<Path> walk(Path start,
3450 FileVisitOption... options)
3451 throws IOException
3452 {
3453 return walk(start, Integer.MAX_VALUE, options);
3454 }
3455
3456 /**
3457 * Return a {@code CloseableStream} that is lazily populated with {@code
3458 * Path} by searching for files in a file tree rooted at a given starting
3459 * file.
3460 *
3461 * <p> This method walks the file tree in exactly the manner specified by
3462 * the {@link #walk walk} method. For each file encountered, the given
3463 * {@link BiPredicate} is invoked with its {@link Path} and {@link
3464 * BasicFileAttributes}. The {@code Path} object is obtained as if by
3465 * {@link Path#resolve(Path) resolving} the relative path against {@code
3466 * start} and is only included in the returned {@link CloseableStream} if
3467 * the {@code BiPredicate} returns true. Compare to calling {@link
3468 * java.util.stream.Stream#filter filter} on the {@code Stream}
3469 * returned by {@code walk} method, this method may be more efficient by
3470 * avoiding redundant retrieval of the {@code BasicFileAttributes}.
3471 *
3472 * <p> If an {@link IOException} is thrown when accessing the directory
3473 * after returned from this method, it is wrapped in an {@link
3474 * UncheckedIOException} which will be thrown from the method that caused
3475 * the access to take place.
3476 *
3477 * @param start
3478 * the starting file
3479 * @param maxDepth
3480 * the maximum number of directory levels to search
3481 * @param matcher
3482 * the function used to decide whether a file should be included
3483 * in the returned stream
3484 * @param options
3485 * options to configure the traversal
3486 *
3487 * @return the {@link CloseableStream} of {@link Path}
3488 *
3489 * @throws IllegalArgumentException
3490 * if the {@code maxDepth} parameter is negative
3491 * @throws SecurityException
3492 * If the security manager denies access to the starting file.
3493 * In the case of the default provider, the {@link
3494 * SecurityManager#checkRead(String) checkRead} method is invoked
3495 * to check read access to the directory.
3496 * @throws IOException
3497 * if an I/O error is thrown when accessing the starting file.
3498 *
3499 * @see #walk(Path, int, FileVisitOption...)
3500 * @since 1.8
3501 */
3502 public static CloseableStream<Path> find(Path start,
3503 int maxDepth,
3504 BiPredicate<Path, BasicFileAttributes> matcher,
3505 FileVisitOption... options)
3506 throws IOException
3507 {
3508 FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
3509
3510 Stream<Path> s = StreamSupport.stream(
3511 Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT),
3512 false).
3513 filter(entry -> matcher.test(entry.file(), entry.attributes())).
3514 map(entry -> entry.file());
3515 return new DelegatingCloseableStream<>(iterator, s);
3516 }
3517
3518 /**
3519 * Read all lines from a file as a {@code CloseableStream}. Unlike {@link
3520 * #readAllLines(Path, Charset) readAllLines}, this method does not read
3521 * all lines into a {@code List}, but instead populates lazily as the stream
3522 * is consumed.
3523 *
3524 * <p> Bytes from the file are decoded into characters using the specified
3525 * charset and the same line terminators as specified by {@code
3526 * readAllLines} are supported.
3527 *
3528 * <p> After this method returns, then any subsequent I/O exception that
3529 * occurs while reading from the file or when a malformed or unmappable byte
3530 * sequence is read, is wrapped in an {@link UncheckedIOException} that will
3531 * be thrown form the
3532 * {@link java.util.stream.Stream} method that caused the read to take
3533 * place. In case an {@code IOException} is thrown when closing the file,
3534 * it is also wrapped as an {@code UncheckedIOException}.
3535 *
3536 * <p> When not using the try-with-resources construct, then stream's
3537 * {@link CloseableStream#close close} method should be invoked after
3538 * operation is completed so as to free any resources held for the open
3539 * file.
3540 *
3541 * @param path
3542 * the path to the file
3543 * @param cs
3544 * the charset to use for decoding
3545 *
3546 * @return the lines from the file as a {@code CloseableStream}
3547 *
3548 * @throws IOException
3549 * if an I/O error occurs opening the file
3550 * @throws SecurityException
3551 * In the case of the default provider, and a security manager is
3552 * installed, the {@link SecurityManager#checkRead(String) checkRead}
3553 * method is invoked to check read access to the file.
3554 *
3555 * @see #readAllLines(Path, Charset)
3556 * @see #newBufferedReader(Path, Charset)
3557 * @see java.io.BufferedReader#lines()
3558 * @since 1.8
3559 */
3560 public static CloseableStream<String> lines(Path path, Charset cs)
3561 throws IOException
3562 {
3563 BufferedReader br = Files.newBufferedReader(path, cs);
3564 return new DelegatingCloseableStream<>(br, br.lines());
3565 }
3566 }
|
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.channels.Channels;
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.Objects;
71 import java.util.ServiceLoader;
72 import java.util.Set;
73 import java.util.Spliterator;
74 import java.util.Spliterators;
75 import java.util.function.BiPredicate;
76 import java.util.stream.Stream;
77 import java.util.stream.StreamSupport;
78
79 /**
80 * This class consists exclusively of static methods that operate on files,
81 * directories, or other types of files.
82 *
83 * <p> In most cases, the methods defined here will delegate to the associated
84 * file system provider to perform the file operations.
85 *
86 * @since 1.7
87 */
88
89 public final class Files {
90 private Files() { }
91
92 /**
93 * Returns the {@code FileSystemProvider} to delegate to.
94 */
95 private static FileSystemProvider provider(Path path) {
96 return path.getFileSystem().provider();
97 }
98
99 /**
100 * Convert a Closeable to a Runnable by converting checked IOException
101 * to UncheckedIOException
102 */
103 private static Runnable asUncheckedRunnable(Closeable c) {
104 return () -> {
105 try {
106 c.close();
107 }
108 catch (IOException e) {
109 throw new UncheckedIOException(e);
110 }
111 };
112 }
113
114 // -- File contents --
115
116 /**
117 * Opens a file, returning an input stream to read from the file. The stream
118 * will not be buffered, and is not required to support the {@link
119 * InputStream#mark mark} or {@link InputStream#reset reset} methods. The
120 * stream will be safe for access by multiple concurrent threads. Reading
121 * commences at the beginning of the file. Whether the returned stream is
122 * <i>asynchronously closeable</i> and/or <i>interruptible</i> is highly
123 * file system provider specific and therefore not specified.
124 *
125 * <p> The {@code options} parameter determines how the file is opened.
126 * If no options are present then it is equivalent to opening the file with
127 * the {@link StandardOpenOption#READ READ} option. In addition to the {@code
128 * READ} option, an implementation may also support additional implementation
129 * specific options.
130 *
131 * @param path
132 * the path to the file to open
133 * @param options
3248 public static Path write(Path path, Iterable<? extends CharSequence> lines,
3249 Charset cs, OpenOption... options)
3250 throws IOException
3251 {
3252 // ensure lines is not null before opening file
3253 Objects.requireNonNull(lines);
3254 CharsetEncoder encoder = cs.newEncoder();
3255 OutputStream out = newOutputStream(path, options);
3256 try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, encoder))) {
3257 for (CharSequence line: lines) {
3258 writer.append(line);
3259 writer.newLine();
3260 }
3261 }
3262 return path;
3263 }
3264
3265 // -- Stream APIs --
3266
3267 /**
3268 * Return a lazily populated {@code Stream}, the elements of
3269 * which are the entries in the directory. The listing is not recursive.
3270 *
3271 * <p> The elements of the stream are {@link Path} objects that are
3272 * obtained as if by {@link Path#resolve(Path) resolving} the name of the
3273 * directory entry against {@code dir}. Some file systems maintain special
3274 * links to the directory itself and the directory's parent directory.
3275 * Entries representing these links are not included.
3276 *
3277 * <p> The stream is <i>weakly consistent</i>. It is thread safe but does
3278 * not freeze the directory while iterating, so it may (or may not)
3279 * reflect updates to the directory that occur after returning from this
3280 * method.
3281 *
3282 * <p> The returned stream encapsulates a {@link DirectoryStream}.
3283 * If timely disposal of file system resources is required, the
3284 * {@code try}-with-resources construct should be used to ensure that the
3285 * stream's {@link Stream#close close} method is invoked after the stream
3286 * operations are completed.
3287 *
3288 * <p> Operating on a closed stream behaves as if the end of stream
3289 * has been reached. Due to read-ahead, one or more elements may be
3290 * returned after the stream has been closed.
3291 *
3292 * <p> If an {@link IOException} is thrown when accessing the directory
3293 * after this method has returned, it is wrapped in an {@link
3294 * UncheckedIOException} which will be thrown from the method that caused
3295 * the access to take place.
3296 *
3297 * @param dir The path to the directory
3298 *
3299 * @return The {@code Stream} describing the content of the
3300 * directory
3301 *
3302 * @throws NotDirectoryException
3303 * if the file could not otherwise be opened because it is not
3304 * a directory <i>(optional specific exception)</i>
3305 * @throws IOException
3306 * if an I/O error occurs when opening the directory
3307 * @throws SecurityException
3308 * In the case of the default provider, and a security manager is
3309 * installed, the {@link SecurityManager#checkRead(String) checkRead}
3310 * method is invoked to check read access to the directory.
3311 *
3312 * @see #newDirectoryStream(Path)
3313 * @since 1.8
3314 */
3315 public static Stream<Path> list(Path dir) throws IOException {
3316 DirectoryStream<Path> ds = Files.newDirectoryStream(dir);
3317 try {
3318 final Iterator<Path> delegate = ds.iterator();
3319
3320 // Re-wrap DirectoryIteratorException to UncheckedIOException
3321 Iterator<Path> it = new Iterator<Path>() {
3322 @Override
3323 public boolean hasNext() {
3324 try {
3325 return delegate.hasNext();
3326 } catch (DirectoryIteratorException e) {
3327 throw new UncheckedIOException(e.getCause());
3328 }
3329 }
3330 @Override
3331 public Path next() {
3332 try {
3333 return delegate.next();
3334 } catch (DirectoryIteratorException e) {
3335 throw new UncheckedIOException(e.getCause());
3336 }
3337 }
3338 };
3339
3340 return StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, Spliterator.DISTINCT), false)
3341 .onClose(asUncheckedRunnable(ds));
3342 } catch (Error|RuntimeException e) {
3343 try {
3344 ds.close();
3345 } catch (IOException ex) {
3346 try {
3347 e.addSuppressed(ex);
3348 } catch (Throwable ignore) {}
3349 }
3350 throw e;
3351 }
3352 }
3353
3354 /**
3355 * Return a {@code Stream} that is lazily populated with {@code
3356 * Path} by walking the file tree rooted at a given starting file. The
3357 * file tree is traversed <em>depth-first</em>, the elements in the stream
3358 * are {@link Path} objects that are obtained as if by {@link
3359 * Path#resolve(Path) resolving} the relative path against {@code start}.
3360 *
3361 * <p> The {@code stream} walks the file tree as elements are consumed.
3362 * The {@code Stream} returned is guaranteed to have at least one
3363 * element, the starting file itself. For each file visited, the stream
3364 * attempts to read its {@link BasicFileAttributes}. If the file is a
3365 * directory and can be opened successfully, entries in the directory, and
3366 * their <em>descendants</em> will follow the directory in the stream as
3367 * they are encountered. When all entries have been visited, then the
3368 * directory is closed. The file tree walk then continues at the next
3369 * <em>sibling</em> of the directory.
3370 *
3371 * <p> The stream is <i>weakly consistent</i>. It does not freeze the
3372 * file tree while iterating, so it may (or may not) reflect updates to
3373 * the file tree that occur after returned from this method.
3374 *
3375 * <p> By default, symbolic links are not automatically followed by this
3376 * method. If the {@code options} parameter contains the {@link
3377 * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then symbolic links are
3378 * followed. When following links, and the attributes of the target cannot
3379 * be read, then this method attempts to get the {@code BasicFileAttributes}
3380 * of the link.
3381 *
3382 * <p> If the {@code options} parameter contains the {@link
3383 * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then the stream keeps
3384 * track of directories visited so that cycles can be detected. A cycle
3385 * arises when there is an entry in a directory that is an ancestor of the
3386 * directory. Cycle detection is done by recording the {@link
3387 * java.nio.file.attribute.BasicFileAttributes#fileKey file-key} of directories,
3388 * or if file keys are not available, by invoking the {@link #isSameFile
3389 * isSameFile} method to test if a directory is the same file as an
3390 * ancestor. When a cycle is detected it is treated as an I/O error with
3391 * an instance of {@link FileSystemLoopException}.
3392 *
3393 * <p> The {@code maxDepth} parameter is the maximum number of levels of
3394 * directories to visit. A value of {@code 0} means that only the starting
3395 * file is visited, unless denied by the security manager. A value of
3396 * {@link Integer#MAX_VALUE MAX_VALUE} may be used to indicate that all
3397 * levels should be visited.
3398 *
3399 * <p> When a security manager is installed and it denies access to a file
3400 * (or directory), then it is ignored and not included in the stream.
3401 *
3402 * <p> The returned stream encapsulates one or more {@link DirectoryStream}s.
3403 * If timely disposal of file system resources is required, the
3404 * {@code try}-with-resources construct should be used to ensure that the
3405 * stream's {@link Stream#close close} method is invoked after the stream
3406 * operations are completed. Operating on a closed stream will result in an
3407 * {@link java.lang.IllegalStateException}.
3408 *
3409 * <p> If an {@link IOException} is thrown when accessing the directory
3410 * after this method has returned, it is wrapped in an {@link
3411 * UncheckedIOException} which will be thrown from the method that caused
3412 * the access to take place.
3413 *
3414 * @param start
3415 * the starting file
3416 * @param maxDepth
3417 * the maximum number of directory levels to visit
3418 * @param options
3419 * options to configure the traversal
3420 *
3421 * @return the {@link Stream} of {@link Path}
3422 *
3423 * @throws IllegalArgumentException
3424 * if the {@code maxDepth} parameter is negative
3425 * @throws SecurityException
3426 * If the security manager denies access to the starting file.
3427 * In the case of the default provider, the {@link
3428 * SecurityManager#checkRead(String) checkRead} method is invoked
3429 * to check read access to the directory.
3430 * @throws IOException
3431 * if an I/O error is thrown when accessing the starting file.
3432 * @since 1.8
3433 */
3434 public static Stream<Path> walk(Path start, int maxDepth,
3435 FileVisitOption... options)
3436 throws IOException {
3437 FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
3438 try {
3439 return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT), false)
3440 .onClose(iterator::close)
3441 .map(entry -> entry.file());
3442 } catch (Error|RuntimeException e) {
3443 iterator.close();
3444 throw e;
3445 }
3446 }
3447
3448 /**
3449 * Return a {@code Stream} that is lazily populated with {@code
3450 * Path} by walking the file tree rooted at a given starting file. The
3451 * file tree is traversed <em>depth-first</em>, the elements in the stream
3452 * are {@link Path} objects that are obtained as if by {@link
3453 * Path#resolve(Path) resolving} the relative path against {@code start}.
3454 *
3455 * <p> This method works as if invoking it were equivalent to evaluating the
3456 * expression:
3457 * <blockquote><pre>
3458 * walk(start, Integer.MAX_VALUE, options)
3459 * </pre></blockquote>
3460 * In other words, it visits all levels of the file tree.
3461 *
3462 * <p> The returned stream encapsulates one or more {@link DirectoryStream}s.
3463 * If timely disposal of file system resources is required, the
3464 * {@code try}-with-resources construct should be used to ensure that the
3465 * stream's {@link Stream#close close} method is invoked after the stream
3466 * operations are completed. Operating on a closed stream will result in an
3467 * {@link java.lang.IllegalStateException}.
3468 *
3469 * @param start
3470 * the starting file
3471 * @param options
3472 * options to configure the traversal
3473 *
3474 * @return the {@link Stream} of {@link Path}
3475 *
3476 * @throws SecurityException
3477 * If the security manager denies access to the starting file.
3478 * In the case of the default provider, the {@link
3479 * SecurityManager#checkRead(String) checkRead} method is invoked
3480 * to check read access to the directory.
3481 * @throws IOException
3482 * if an I/O error is thrown when accessing the starting file.
3483 *
3484 * @see #walk(Path, int, FileVisitOption...)
3485 * @since 1.8
3486 */
3487 public static Stream<Path> walk(Path start,
3488 FileVisitOption... options)
3489 throws IOException {
3490 return walk(start, Integer.MAX_VALUE, options);
3491 }
3492
3493 /**
3494 * Return a {@code Stream} that is lazily populated with {@code
3495 * Path} by searching for files in a file tree rooted at a given starting
3496 * file.
3497 *
3498 * <p> This method walks the file tree in exactly the manner specified by
3499 * the {@link #walk walk} method. For each file encountered, the given
3500 * {@link BiPredicate} is invoked with its {@link Path} and {@link
3501 * BasicFileAttributes}. The {@code Path} object is obtained as if by
3502 * {@link Path#resolve(Path) resolving} the relative path against {@code
3503 * start} and is only included in the returned {@link Stream} if
3504 * the {@code BiPredicate} returns true. Compare to calling {@link
3505 * java.util.stream.Stream#filter filter} on the {@code Stream}
3506 * returned by {@code walk} method, this method may be more efficient by
3507 * avoiding redundant retrieval of the {@code BasicFileAttributes}.
3508 *
3509 * <p> The returned stream encapsulates one or more {@link DirectoryStream}s.
3510 * If timely disposal of file system resources is required, the
3511 * {@code try}-with-resources construct should be used to ensure that the
3512 * stream's {@link Stream#close close} method is invoked after the stream
3513 * operations are completed. Operating on a closed stream will result in an
3514 * {@link java.lang.IllegalStateException}.
3515 *
3516 * <p> If an {@link IOException} is thrown when accessing the directory
3517 * after returned from this method, it is wrapped in an {@link
3518 * UncheckedIOException} which will be thrown from the method that caused
3519 * the access to take place.
3520 *
3521 * @param start
3522 * the starting file
3523 * @param maxDepth
3524 * the maximum number of directory levels to search
3525 * @param matcher
3526 * the function used to decide whether a file should be included
3527 * in the returned stream
3528 * @param options
3529 * options to configure the traversal
3530 *
3531 * @return the {@link Stream} of {@link Path}
3532 *
3533 * @throws IllegalArgumentException
3534 * if the {@code maxDepth} parameter is negative
3535 * @throws SecurityException
3536 * If the security manager denies access to the starting file.
3537 * In the case of the default provider, the {@link
3538 * SecurityManager#checkRead(String) checkRead} method is invoked
3539 * to check read access to the directory.
3540 * @throws IOException
3541 * if an I/O error is thrown when accessing the starting file.
3542 *
3543 * @see #walk(Path, int, FileVisitOption...)
3544 * @since 1.8
3545 */
3546 public static Stream<Path> find(Path start,
3547 int maxDepth,
3548 BiPredicate<Path, BasicFileAttributes> matcher,
3549 FileVisitOption... options)
3550 throws IOException {
3551 FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
3552 try {
3553 return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT), false)
3554 .onClose(iterator::close)
3555 .filter(entry -> matcher.test(entry.file(), entry.attributes()))
3556 .map(entry -> entry.file());
3557 } catch (Error|RuntimeException e) {
3558 iterator.close();
3559 throw e;
3560 }
3561 }
3562
3563 /**
3564 * Read all lines from a file as a {@code Stream}. Unlike {@link
3565 * #readAllLines(Path, Charset) readAllLines}, this method does not read
3566 * all lines into a {@code List}, but instead populates lazily as the stream
3567 * is consumed.
3568 *
3569 * <p> Bytes from the file are decoded into characters using the specified
3570 * charset and the same line terminators as specified by {@code
3571 * readAllLines} are supported.
3572 *
3573 * <p> After this method returns, then any subsequent I/O exception that
3574 * occurs while reading from the file or when a malformed or unmappable byte
3575 * sequence is read, is wrapped in an {@link UncheckedIOException} that will
3576 * be thrown from the
3577 * {@link java.util.stream.Stream} method that caused the read to take
3578 * place. In case an {@code IOException} is thrown when closing the file,
3579 * it is also wrapped as an {@code UncheckedIOException}.
3580 *
3581 * <p> The returned stream encapsulates a {@link Reader}. If timely
3582 * disposal of file system resources is required, the try-with-resources
3583 * construct should be used to ensure that the stream's
3584 * {@link Stream#close close} method is invoked after the stream operations
3585 * are completed.
3586 *
3587 *
3588 * @param path
3589 * the path to the file
3590 * @param cs
3591 * the charset to use for decoding
3592 *
3593 * @return the lines from the file as a {@code Stream}
3594 *
3595 * @throws IOException
3596 * if an I/O error occurs opening the file
3597 * @throws SecurityException
3598 * In the case of the default provider, and a security manager is
3599 * installed, the {@link SecurityManager#checkRead(String) checkRead}
3600 * method is invoked to check read access to the file.
3601 *
3602 * @see #readAllLines(Path, Charset)
3603 * @see #newBufferedReader(Path, Charset)
3604 * @see java.io.BufferedReader#lines()
3605 * @since 1.8
3606 */
3607 public static Stream<String> lines(Path path, Charset cs) throws IOException {
3608 BufferedReader br = Files.newBufferedReader(path, cs);
3609 try {
3610 return br.lines().onClose(asUncheckedRunnable(br));
3611 } catch (Error|RuntimeException e) {
3612 try {
3613 br.close();
3614 } catch (IOException ex) {
3615 try {
3616 e.addSuppressed(ex);
3617 } catch (Throwable ignore) {}
3618 }
3619 throw e;
3620 }
3621 }
3622 }
|