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 }
|