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.SeekableByteChannel;
32 import java.io.InputStream;
33 import java.io.OutputStream;
34 import java.io.Reader;
35 import java.io.Writer;
36 import java.io.BufferedReader;
37 import java.io.BufferedWriter;
38 import java.io.InputStreamReader;
39 import java.io.OutputStreamWriter;
40 import java.io.IOException;
41 import java.util.*;
42 import java.security.AccessController;
43 import java.security.PrivilegedAction;
44 import java.nio.charset.Charset;
45 import java.nio.charset.CharsetDecoder;
46 import java.nio.charset.CharsetEncoder;
47
48 /**
49 * This class consists exclusively of static methods that operate on files,
50 * directories, or other types of files.
51 *
52 * <p> In most cases, the methods defined here will delegate to the associated
53 * file system provider to perform the file operations.
54 *
55 * @since 1.7
56 */
57
58 public final class Files {
59 private Files() { }
60
61 /**
2570 * the file visitor to invoke for each file
2571 *
2572 * @return the starting file
2573 *
2574 * @throws IllegalArgumentException
2575 * if the {@code maxDepth} parameter is negative
2576 * @throws SecurityException
2577 * If the security manager denies access to the starting file.
2578 * In the case of the default provider, the {@link
2579 * SecurityManager#checkRead(String) checkRead} method is invoked
2580 * to check read access to the directory.
2581 * @throws IOException
2582 * if an I/O error is thrown by a visitor method
2583 */
2584 public static Path walkFileTree(Path start,
2585 Set<FileVisitOption> options,
2586 int maxDepth,
2587 FileVisitor<? super Path> visitor)
2588 throws IOException
2589 {
2590 if (maxDepth < 0)
2591 throw new IllegalArgumentException("'maxDepth' is negative");
2592
2593 /**
2594 * Create a FileTreeWalker to walk the file tree, invoking the visitor
2595 * for each event.
2596 */
2597 try (FileTreeWalker walker = new FileTreeWalker(options, maxDepth)) {
2598 FileTreeWalker.Event ev = walker.walk(start);
2599 do {
2600 FileVisitResult result;
2601 switch (ev.type()) {
2602 case ENTRY :
2603 IOException ioe = ev.ioeException();
2604 if (ioe == null) {
2605 assert ev.attributes() != null;
2606 result = visitor.visitFile(ev.file(), ev.attributes());
2607 } else {
2608 result = visitor.visitFileFailed(ev.file(), ioe);
2609 }
2610 break;
2611
2612 case START_DIRECTORY :
3159 * @throws SecurityException
3160 * In the case of the default provider, and a security manager is
3161 * installed, the {@link SecurityManager#checkWrite(String) checkWrite}
3162 * method is invoked to check write access to the file.
3163 */
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 }
|
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.SeekableByteChannel;
32 import java.io.Closeable;
33 import java.io.InputStream;
34 import java.io.OutputStream;
35 import java.io.Reader;
36 import java.io.Writer;
37 import java.io.BufferedReader;
38 import java.io.BufferedWriter;
39 import java.io.InputStreamReader;
40 import java.io.OutputStreamWriter;
41 import java.io.IOException;
42 import java.io.UncheckedIOException;
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;
49 import java.security.AccessController;
50 import java.security.PrivilegedAction;
51 import java.nio.charset.Charset;
52 import java.nio.charset.CharsetDecoder;
53 import java.nio.charset.CharsetEncoder;
54
55 /**
56 * This class consists exclusively of static methods that operate on files,
57 * directories, or other types of files.
58 *
59 * <p> In most cases, the methods defined here will delegate to the associated
60 * file system provider to perform the file operations.
61 *
62 * @since 1.7
63 */
64
65 public final class Files {
66 private Files() { }
67
68 /**
2577 * the file visitor to invoke for each file
2578 *
2579 * @return the starting file
2580 *
2581 * @throws IllegalArgumentException
2582 * if the {@code maxDepth} parameter is negative
2583 * @throws SecurityException
2584 * If the security manager denies access to the starting file.
2585 * In the case of the default provider, the {@link
2586 * SecurityManager#checkRead(String) checkRead} method is invoked
2587 * to check read access to the directory.
2588 * @throws IOException
2589 * if an I/O error is thrown by a visitor method
2590 */
2591 public static Path walkFileTree(Path start,
2592 Set<FileVisitOption> options,
2593 int maxDepth,
2594 FileVisitor<? super Path> visitor)
2595 throws IOException
2596 {
2597 /**
2598 * Create a FileTreeWalker to walk the file tree, invoking the visitor
2599 * for each event.
2600 */
2601 try (FileTreeWalker walker = new FileTreeWalker(options, maxDepth)) {
2602 FileTreeWalker.Event ev = walker.walk(start);
2603 do {
2604 FileVisitResult result;
2605 switch (ev.type()) {
2606 case ENTRY :
2607 IOException ioe = ev.ioeException();
2608 if (ioe == null) {
2609 assert ev.attributes() != null;
2610 result = visitor.visitFile(ev.file(), ev.attributes());
2611 } else {
2612 result = visitor.visitFileFailed(ev.file(), ioe);
2613 }
2614 break;
2615
2616 case START_DIRECTORY :
3163 * @throws SecurityException
3164 * In the case of the default provider, and a security manager is
3165 * installed, the {@link SecurityManager#checkWrite(String) checkWrite}
3166 * method is invoked to check write access to the file.
3167 */
3168 public static Path write(Path path, Iterable<? extends CharSequence> lines,
3169 Charset cs, OpenOption... options)
3170 throws IOException
3171 {
3172 // ensure lines is not null before opening file
3173 Objects.requireNonNull(lines);
3174 CharsetEncoder encoder = cs.newEncoder();
3175 OutputStream out = newOutputStream(path, options);
3176 try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, encoder))) {
3177 for (CharSequence line: lines) {
3178 writer.append(line);
3179 writer.newLine();
3180 }
3181 }
3182 return path;
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 obtained
3214 * as if by {@link Path#resolve(Path) resolving} the name of the directory
3215 * entry against {@code dir}. Some file systems maintain special links to
3216 * the directory itself and the directory's parent directory. Entries
3217 * 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 returned from this
3222 * method.
3223 *
3224 * <p> When not using the try-with-resources construct, then stream's
3225 * {@link CloseableStream#close close} method should be invoked after
3226 * operation is completed so as to free any resources held for the open
3227 * directory.
3228 *
3229 * <p> If an {@link IOException} is thrown when accessing the directory
3230 * after this method has returned, it is wrapped in an {@link
3231 * UncheckedIOException} which will be thrown from the method that caused
3232 * the access to take place.
3233 *
3234 * @param dir The path to the directory
3235 *
3236 * @return The {@code CloseableStream} describing the content of the
3237 * directory
3238 *
3239 * @throws NotDirectoryException
3240 * if the file could not otherwise be opened because it is not
3241 * a directory <i>(optional specific exception)</i>
3242 * @throws IOException
3243 * if an I/O error occurs when opening the directory
3244 * @throws SecurityException
3245 * In the case of the default provider, and a security manager is
3246 * installed, the {@link SecurityManager#checkRead(String) checkRead}
3247 * method is invoked to check read access to the directory.
3248 *
3249 * @see #newDirectoryStream(Path)
3250 * @see DirectoryStream#entries()
3251 * @since 1.8
3252 */
3253 public static CloseableStream<Path> list(Path dir) throws IOException {
3254 DirectoryStream<Path> ds = Files.newDirectoryStream(dir);
3255 final Iterator<Path> delegate = ds.iterator();
3256
3257 // Re-wrap DirectoryIteratorException to UncheckedIOException
3258 Iterator<Path> it = new Iterator<Path>() {
3259 public boolean hasNext() {
3260 try {
3261 return delegate.hasNext();
3262 } catch (DirectoryIteratorException e) {
3263 throw new UncheckedIOException(e.getCause());
3264 }
3265 }
3266 public Path next() {
3267 try {
3268 return delegate.next();
3269 } catch (DirectoryIteratorException e) {
3270 throw new UncheckedIOException(e.getCause());
3271 }
3272 }
3273 };
3274
3275 return new DelegatingCloseableStream<>(ds,
3276 StreamSupport.stream(Spliterators.spliteratorUnknownSize(it,
3277 Spliterator.DISTINCT)));
3278 }
3279
3280 /**
3281 * Return a {@code CloseableStream} that is lazily populated with {@code
3282 * Path} by walking the file tree rooted at a given starting file. The
3283 * file tree is traversed <em>depth-first</em>, the elements in the stream
3284 * are {@link Path} objects that are obtained as if by {@link
3285 * Path#resolve(Path) resolving} the relative path against {@code start}.
3286 *
3287 * <p> The {@code stream} walks the file tree as elements are consumed.
3288 * The {@code CloseableStream} returned is guaranteed to have at least one
3289 * element, the starting file itself. For each file visited, the stream
3290 * attempts to read its {@link BasicFileAttributes}. If the file is a
3291 * directory and can be opened successfully, entries in the directory, and
3292 * their <em>descendants</em> will follow the directory in the stream as
3293 * they are encountered. When all entries have been visited, then the
3294 * directory is closed. The file tree walk then continues at the next
3295 * <em>sibling</em> of the directory.
3296 *
3297 * <p> The stream is <i>weakly consistent</i>. It does not freeze the
3298 * file tree while iterating, so it may (or may not) reflect updates to
3299 * the file tree that occur after returned from this method.
3300 *
3301 * <p> By default, symbolic links are not automatically followed by this
3302 * method. If the {@code options} parameter contains the {@link
3303 * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then symbolic links are
3304 * followed. When following links, and the attributes of the target cannot
3305 * be read, then this method attempts to get the {@code BasicFileAttributes}
3306 * of the link.
3307 *
3308 * <p> If the {@code options} parameter contains the {@link
3309 * FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then the stream keeps
3310 * track of directories visited so that cycles can be detected. A cycle
3311 * arises when there is an entry in a directory that is an ancestor of the
3312 * directory. Cycle detection is done by recording the {@link
3313 * java.nio.file.attribute.BasicFileAttributes#fileKey file-key} of directories,
3314 * or if file keys are not available, by invoking the {@link #isSameFile
3315 * isSameFile} method to test if a directory is the same file as an
3316 * ancestor. When a cycle is detected it is treated as an I/O error with
3317 * an instance of {@link FileSystemLoopException}.
3318 *
3319 * <p> The {@code maxDepth} parameter is the maximum number of levels of
3320 * directories to visit. A value of {@code 0} means that only the starting
3321 * file is visited, unless denied by the security manager. A value of
3322 * {@link Integer#MAX_VALUE MAX_VALUE} may be used to indicate that all
3323 * levels should be visited.
3324 *
3325 * <p> When a security manager is installed and it denies access to a file
3326 * (or directory), then it is ignored and not included in the stream.
3327 *
3328 * <p> When not using the try-with-resources construct, then stream's
3329 * {@link CloseableStream#close close} method should be invoked after
3330 * operation is completed so as to free any resources held for the open
3331 * directory.
3332 *
3333 * <p> If an {@link IOException} is thrown when accessing the directory
3334 * after this method has returned, it is wrapped in an {@link
3335 * UncheckedIOException} which will be thrown from the method that caused
3336 * the access to take place.
3337 *
3338 * @param start
3339 * the starting file
3340 * @param maxDepth
3341 * the maximum number of directory levels to visit
3342 * @param options
3343 * options to configure the traversal
3344 *
3345 * @return the {@link CloseableStream} of {@link Path}
3346 *
3347 * @throws IllegalArgumentException
3348 * if the {@code maxDepth} parameter is negative
3349 * @throws SecurityException
3350 * If the security manager denies access to the starting file.
3351 * In the case of the default provider, the {@link
3352 * SecurityManager#checkRead(String) checkRead} method is invoked
3353 * to check read access to the directory.
3354 * @throws IOException
3355 * if an I/O error is thrown when accessing the starting file.
3356 * @since 1.8
3357 */
3358 public static CloseableStream<Path> walk(Path start, int maxDepth,
3359 FileVisitOption... options)
3360 throws IOException
3361 {
3362 FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
3363 return new DelegatingCloseableStream<>(iterator,
3364 StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT))
3365 .map(entry -> entry.file()));
3366 }
3367
3368 /**
3369 * Return a {@code CloseableStream} that is lazily populated with {@code
3370 * Path} by walking the file tree rooted at a given starting file. The
3371 * file tree is traversed <em>depth-first</em>, the elements in the stream
3372 * are {@link Path} objects that are obtained as if by {@link
3373 * Path#resolve(Path) resolving} the relative path against {@code start}.
3374 *
3375 * <p> This method works as if invoking it were equivalent to evaluating the
3376 * expression:
3377 * <blockquote><pre>
3378 * walk(start, Integer.MAX_VALUE, options)
3379 * </pre></blockquote>
3380 * In other words, it visits all levels of the file tree.
3381 *
3382 * @param start
3383 * the starting file
3384 * @param options
3385 * options to configure the traversal
3386 *
3387 * @return the {@link CloseableStream} of {@link Path}
3388 *
3389 * @throws SecurityException
3390 * If the security manager denies access to the starting file.
3391 * In the case of the default provider, the {@link
3392 * SecurityManager#checkRead(String) checkRead} method is invoked
3393 * to check read access to the directory.
3394 * @throws IOException
3395 * if an I/O error is thrown when accessing the starting file.
3396 *
3397 * @see #walk(Path, int, FileVisitOption...)
3398 * @since 1.8
3399 */
3400 public static CloseableStream<Path> walk(Path start,
3401 FileVisitOption... options)
3402 throws IOException
3403 {
3404 return walk(start, Integer.MAX_VALUE, options);
3405 }
3406
3407 /**
3408 * Return a {@code CloseableStream} that is lazily populated with {@code
3409 * Path} by searching for files in a file tree rooted at a given starting
3410 * file.
3411 *
3412 * <p>This method walks the file tree in exactly the manner specified by
3413 * the {@link #walk walk} method. For each file encountered, the given
3414 * {@link BiPredicate} is invoked with its {@link Path} and {@link
3415 * BasicFileAttributes}. The {@code Path} object is obtained as if by
3416 * {@link Path#resolve(Path) resolving} the relative path against {@code
3417 * start} and is only included in the returned {@link CloseableStream} if
3418 * the {@code BiPredicate} returns true. Compare to calling {@link
3419 * java.util.stream.Stream#filter filter} on the {@code Stream} returned
3420 * by {@code walk} method, this method is more efficient by avoiding
3421 * redundant retrieval of the {@code BasicFileAttributes}.
3422 *
3423 * <p>If an {@link IOException} is thrown when accessing the directory
3424 * after returned from this method, it is wrapped in an {@link
3425 * UncheckedIOException} which will be thrown from the method that caused
3426 * the access to take place.
3427 *
3428 * @param start
3429 * the starting file
3430 * @param maxDepth
3431 * the maximum number of directory levels to search
3432 * @param matcher
3433 * the function used to decide whether a file should be included
3434 * in the returned stream
3435 * @param options
3436 * options to configure the traversal
3437 *
3438 * @return the {@link CloseableStream} of {@link Path}
3439 *
3440 * @throws IllegalArgumentException
3441 * if the {@code maxDepth} parameter is negative
3442 * @throws SecurityException
3443 * If the security manager denies access to the starting file.
3444 * In the case of the default provider, the {@link
3445 * SecurityManager#checkRead(String) checkRead} method is invoked
3446 * to check read access to the directory.
3447 * @throws IOException
3448 * if an I/O error is thrown when accessing the starting file.
3449 *
3450 * @see #walk(Path, int, FileVisitOption...)
3451 * @since 1.8
3452 */
3453 public static CloseableStream<Path> find(Path start,
3454 int maxDepth,
3455 BiPredicate<Path, BasicFileAttributes> matcher,
3456 FileVisitOption... options)
3457 throws IOException
3458 {
3459 FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
3460 return new DelegatingCloseableStream<>(iterator,
3461 StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT))
3462 .filter(entry -> matcher.test(entry.file(), entry.attributes()))
3463 .map(entry -> entry.file()));
3464 }
3465
3466 /**
3467 * Read all lines from a file as a {@code CloseableStream}. Unlike {@link
3468 * #readAllLines(Path, Charset) readAllLines}, this method does not read
3469 * all lines into a {@code List}, but instead populates lazily as the stream
3470 * is consumed.
3471 *
3472 * <p> Bytes from the file are decoded into characters using the specified
3473 * charset and the same line terminators as specified by {@code
3474 * readAllLines} are supported.
3475 *
3476 * <p> After this method returns, then any subsequent I/O exception that
3477 * occurs while reading from the file or when a malformed or unmappable byte
3478 * sequence is read, is wrapped in an {@link UncheckedIOException} that will
3479 * be thrown form the
3480 * {@link java.util.stream.Stream} method that caused the read to take
3481 * place. In case an {@code IOException} is thrown when closing the file,
3482 * it is also wrapped as an {@code UncheckedIOException}.
3483 *
3484 * <p> When not using the try-with-resources construct, then stream's
3485 * {@link CloseableStream#close close} method should be invoked after
3486 * operation is completed so as to free any resources held for the open
3487 * file.
3488 *
3489 * @param path
3490 * the path to the file
3491 * @param cs
3492 * the charset to use for decoding
3493 *
3494 * @return the lines from the file as a {@code CloseableStream}
3495 *
3496 * @throws IOException
3497 * if an I/O error occurs opening the file
3498 * @throws SecurityException
3499 * In the case of the default provider, and a security manager is
3500 * installed, the {@link SecurityManager#checkRead(String) checkRead}
3501 * method is invoked to check read access to the file.
3502 *
3503 * @see #readAllLines(Path, Charset)
3504 * @see #newBufferedReader(Path, Charset)
3505 * @see java.io.BufferedReader#lines()
3506 * @since 1.8
3507 */
3508 public static CloseableStream<String> lines(Path path, Charset cs)
3509 throws IOException
3510 {
3511 BufferedReader br = Files.newBufferedReader(path, cs);
3512 return new DelegatingCloseableStream<>(br, br.lines());
3513 }
3514 }
|