-
Notifications
You must be signed in to change notification settings - Fork 90
/
ch24.html
766 lines (515 loc) · 56.9 KB
/
ch24.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
<!doctype html>
<html lang="en">
<head>
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Study guide for the Oracle Certified Professional, Java SE 8 Programmer Exam ">
<title>Java 8 Programmer II Study Guide: Exam 1Z0-809</title>
<link href="css/code.css" rel="stylesheet" type="text/css" />
<link href="css/style.css" rel="stylesheet" type="text/css" />
<link href="https://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script src="js/common-sections.js"></script>
</head>
<body>
<div class="nav"></div>
<div class="header">
<div class="title-container">
<div class="chapter-title">
<h1><i class="chapter">Chapter TWENTY-FOUR</i><br />
NIO.2</h1>
<p><br /></p>
<h3 style="text-align: center;"><i>Exam Objectives</i></h3>
<p style="text-align: center;"><i>Use Path interface to operate on file and directory paths.<br /></i><i>Use Files class to check, read, delete, copy, move, manage metadata of a file or directory.</i></p>
</div>
</div>
</div>
<div class="container">
<div class="column">
<h2>NIO.2</h2>
<p>In the last chapter, we reviewed the classes of the <code>java.io</code> package.</p>
<p>In the first versions of Java, this package, especially the <code>File</code> class, provided support for file operations. However, it had some problems, like lacking functionality and limited file attribute support.</p>
<p>For that reason, Java 1.4 introduced the NIO (Non-blocking Input/Output) API in the package <code>java.nio</code> implementing new functionality like channels, buffering, and new charsets.</p>
<p>However, this API didn't entirely solve the problems with the <code>java.io</code> package, so in Java 7, the NIO.2 API was added in the <code>java.nio.file</code> package (actually, since this is a new package, NIO.2 is not an update to the NIO API, besides, they focus on different things).</p>
<p>NIO.2 provides better support for accessing files and the file system, symbolic links, interoperability, and exceptions among others.</p>
<p>The primary classes of <code>java.nio.file</code>, <code>Path</code>, <code>Paths</code>, and <code>Files</code>, are intended to provide an easier way to work with files and to be a replacement for the <code>java.io.File</code> class.</p>
<p>These classes will be the focus of this chapter. Let's start with <code>Path</code> and <code>Paths</code>.</p>
<h2>The Path interface</h2>
<p>In the previous chapter, we also reviewed concepts like file systems and paths.</p>
<p>Well, the <code>Path</code> interface defines an object that represents the path to a file or a directory.</p>
<p>When you think about the fact that a path varies between different file systems, it makes sense that <code>Path</code> is an interface. Thanks to this, Java transparently handles different implementations between platforms.</p>
<p>For example, here are some differences between Windows-based and Unix-based systems:</p>
<ul>
<li>Windows-based systems are not case sensitive while Unix-based systems are.</li>
<li>In Windows-based systems, paths are separated by backslashes. In Unix-based systems, by forward slashes.</li>
<li>In Windows-based systems, the root path is a drive letter (generally <code>c:\</code>). In Unix-based systems, it's a forward slash (<code>/</code>).</li>
<li>Because of that, in Windows-based systems, an absolute path starts with a drive letter (like <code>c:\temp\file.txt</code>). In Unix-based systems, it starts with a forward slash (like <code>/temp/file.txt</code>).</li>
</ul>
<p>Since <code>Path</code> is an interface and Java handles its implementations, we have to use a utility class to create <code>Path</code> instances.</p>
<p><code>java.nio.file.Paths</code> is this class. It provides two methods to create a <code>Path</code> object:</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> Path <span class="hljs-title">get</span><span class="hljs-params">(String first, String... more)</span><br />
<span class="hljs-keyword">static</span> Path <span class="hljs-title">get</span><span class="hljs-params">(URI uri)</span></span></code></p>
<p>Be very careful with the names:</p>
<p><b>Path</b> is the <b>interface</b> with methods to work with paths.</p>
<p><b>Paths</b> is the <b>class</b> with <code>static</code> methods to create a <code>Path</code> object.</p>
<p>With the first version of <code>Paths.get()</code> you can create a <code>Path</code> object in these ways:</p>
<p><code class="java hljs"><span class="hljs-comment">// With an absolute path in windows</span><br />
Path pathWin = Paths.get(<span class="hljs-string">"c:\\temp\\file.txt"</span>);<br />
<span class="hljs-comment">// With an absolute path in unix</span><br />
Path pathUnix = Paths.get(<span class="hljs-string">"/temp/file.txt"</span>);<br />
<span class="hljs-comment">// With a relative path</span><br />
Path pathRelative = Paths.get(<span class="hljs-string">"file.txt"</span>);<br />
<span class="hljs-comment">//Using the varargs parameter</span><br />
<span class="hljs-comment">// (the separator is inserted automatically)</span><br />
Path pathByParts = Paths.get(<span class="hljs-string">"c:"</span>, <span class="hljs-string">"temp"</span>, <span class="hljs-string">"file.txt"</span>);</code></p>
<p>With the second version, you have to use a <code>java.net.URI</code> instance. Since we're working with files, the URI schema must be <code>file://</code>:</p>
<p><code class="java hljs"><span class="hljs-keyword">try</span> {<br />
Path fileURI = Paths.get(<span class="hljs-keyword">new</span> URI(<span class="hljs-string">"file:///c:/temp/file.txt"</span>));<br />
} <span class="hljs-keyword">catch</span> (URISyntaxException e) {<br />
<span class="hljs-comment"> //This checked exception is thrown by the URI constructor</span><br />
}</code></p>
<p>If you don't want to catch <code>URISyntaxException</code>, you can use the <code>static</code> method <code>URI.create(String)</code>. It wraps the <code>URISyntaxException</code> exception in an <code>IllegalArgumentException</code> (a subclass of <code>RuntimeException</code>):</p>
<p><code class="java hljs">Path fileURI = Paths.get(URI.create(<span class="hljs-string">"file:///c:/temp/file.txt"</span>));</code></p>
<p>Notice the three slashes. <code>file:///</code> represents an absolute path (the <code>file://</code> schema plus another slash for the root directory). We can test this with the help of the <code>toAbsolutePath()</code> method, which returns the absolute path representation of a <code>Path</code> object:</p>
<p><code class="java hljs">Path fileURI = Paths.get(URI.create(<span class="hljs-string">"file:///file.txt"</span>));<br />
System.out.println(fileURI.toAbsolutePath());</code></p>
<p>This will print either:</p>
<p><code class="java hljs">C:\file.txt <span class="hljs-comment">// in Windows-based systems</span><br />
/file.txt <span class="hljs-comment">// Or in Unix-based systems</span></code></p>
<p>We can also create a <code>Path</code> from a <code>File</code> and vice-versa:</p>
<p><code class="java hljs">File file = <span class="hljs-keyword">new</span> File(<span class="hljs-string">"/file.txt"</span>);<br />
Path path = file.toPath();<br />
<br />
path = Paths.get(<span class="hljs-string">"/file.txt"</span>);<br />
file = path.toFile();</code></p>
<p>And just to make clear that the <code>Path</code> instance is system-dependent, let me tell you that <code>Paths.get()</code> is actually equivalent to:</p>
<p><code class="java hljs">Path path = FileSystems.getDefault().getPath(<span class="hljs-string">"c://temp"</span>);</code></p>
<p>As you can see from the examples, the absolute path representation of a <code>Path</code> object has a root component (either <code>c:\</code> or <code>/</code>) and a sequence of names separated by a (forward or backward) slash.</p>
<p>These names represent the directories needed to navigate to the target file or directory. The last name in the sequence represents the name of the target file or directory.</p>
<p>For example, the elements of the path <code>c:\temp\dir1\file.txt</code> (or its Unix equivalent, <code>/temp/dir1/file.txt</code>) are:</p>
<p><code class="hljs"><b>Root:</b> c:\ (or /)<br />
<b>Name 1:</b> temp<br />
<b>Name 2:</b> dir1<br />
<b>Name 3:</b> file.txt</code></p>
<p>The <code>Path</code> object has some methods to get this information. Except for <code>toString()</code> and <code>getNameCount()</code>, each of these methods returns a <code>Path</code> object):</p>
<p><code class="java hljs">Path path = Paths.get(<span class="hljs-string">"C:\\temp\\dir1\\file.txt"</span>);<br />
<span class="hljs-comment">// Or Path path = Paths.get("/temp/dir1/file.txt");</span><br />
System.out.println(<span class="hljs-string">"toString(): "</span> + path.toString());<br />
System.out.println(<span class="hljs-string">"getFileName(): "</span> + path.getFileName());<br />
System.out.println(<span class="hljs-string">"getNameCount(): "</span> +path.getNameCount());<br />
<span class="hljs-comment">// Indexes start from zero</span> <br />
System.out.println(<span class="hljs-string">"getName(0): "</span> + path.getName(<span class="hljs-number">0</span>));<br />
System.out.println(<span class="hljs-string">"getName(1): "</span> + path.getName(<span class="hljs-number">1</span>));<br />
System.out.println(<span class="hljs-string">"getName(2): "</span> + path.getName(<span class="hljs-number">2</span>));<br />
<span class="hljs-comment">// subpath(beginIndex, endIndex) from beginIndex to endIndex-1</span><br />
System.out.println(<span class="hljs-string">"subpath(0,2): "</span> + path.subpath(<span class="hljs-number">0</span>,<span class="hljs-number">2</span>));<br />
System.out.println(<span class="hljs-string">"getParent(): "</span> + path.getParent());<br />
System.out.println(<span class="hljs-string">"getRoot(): "</span> + path.getRoot());</code></p>
<p>The output:</p>
<p><code class="java hljs">toString(): C:\temp\dir1\file.txt <span class="hljs-comment">// Or /temp/dir1/file.txt</span><br />
getFileName(): file.<span class="hljs-function">txt<br />
<span class="hljs-title">getNameCount</span><span class="hljs-params">()</span>: 3<br />
<span class="hljs-title">getName</span><span class="hljs-params">(<span class="hljs-number">0</span>)</span>: temp<br />
<span class="hljs-title">getName</span><span class="hljs-params">(<span class="hljs-number">1</span>)</span>: dir1<br />
<span class="hljs-title">getName</span><span class="hljs-params">(<span class="hljs-number">2</span>)</span>: file.txt<br />
<span class="hljs-title">subpath</span><span class="hljs-params">(<span class="hljs-number">0</span>,<span class="hljs-number">2</span>)</span>: temp\dir1 <span class="hljs-comment">// Or temp/dir1</span><br />
<span class="hljs-title">getParent</span><span class="hljs-params">()</span>: C:\temp\dir1 <span class="hljs-comment">// Or /temp/dir1</span><br />
<span class="hljs-title">getRoot</span><span class="hljs-params">()</span>: C:\ <span class="hljs-comment">// Or /</span></span></code></p>
<p>Passing an invalid index to <code>getName()</code> and <code>subpath()</code> will throw an <code>IllegalArgumentException</code> (a <code>RuntimeException</code>).</p>
<p>If the path is specified as a relative one (and assuming this code is executed from the <code>c:\temp</code> directory):</p>
<p><code class="java hljs">Path path = Paths.get(<span class="hljs-string">"dir1\\file.txt"</span>);<span class="hljs-comment">// Or dir1/file.txt</span> <br />
System.out.println(<span class="hljs-string">"toString(): "</span> + path.toString());<br />
System.out.println(<span class="hljs-string">"getFileName(): "</span> + path.getFileName());<br />
System.out.println(<span class="hljs-string">"getNameCount(): "</span> + path.getNameCount());<br />
System.out.println(<span class="hljs-string">"getName(0): "</span> + path.getName(<span class="hljs-number">0</span>));<br />
System.out.println(<span class="hljs-string">"getName(1): "</span> + path.getName(<span class="hljs-number">1</span>));<br />
System.out.println(<span class="hljs-string">"subpath(0,2): "</span> + path.subpath(<span class="hljs-number">0</span>,<span class="hljs-number">2</span>));<br />
System.out.println(<span class="hljs-string">"getParent(): "</span> + path.getParent());<br />
System.out.println(<span class="hljs-string">"getRoot(): "</span> + path.getRoot());</code></p>
<p>The output:</p>
<p><code class="java hljs">toString(): dir1\file.txt <span class="hljs-comment">// Or dir1/file.txt</span><br />
getFileName(): file.<span class="hljs-function">txt<br />
<span class="hljs-title">getNameCount</span><span class="hljs-params">()</span>: 2<br />
<span class="hljs-title">getName</span><span class="hljs-params">(<span class="hljs-number">0</span>)</span>: dir1<br />
<span class="hljs-title">getName</span><span class="hljs-params">(<span class="hljs-number">1</span>)</span>: file.txt<br />
<span class="hljs-title">subpath</span><span class="hljs-params">(<span class="hljs-number">0</span>,<span class="hljs-number">2</span>)</span>: dir1\file.txt <span class="hljs-comment">// Or dir1/file.txt</span><br />
<span class="hljs-title">getParent</span><span class="hljs-params">()</span>: dir1<br />
<span class="hljs-title">getRoot</span><span class="hljs-params">()</span>: <span class="hljs-keyword">null</span></span></code></p>
<p>When working with paths, you can use:</p>
<ul>
<li><code>.</code> to refer to the current directory</li>
<li><code>..</code> to refer to the parent directory</li>
</ul>
<p>For example:</p>
<p><code class="java hljs"><span style="color: rgb(0, 106, 0);">// refers to /temp/file.txt<br /></span>Path p1 = Paths.get(<span class="hljs-string">"/temp/./file.txt"</span>); <br />
<span style="color: rgb(0, 106, 0);">// refers to /temp//file.txt<br /></span>Path p2 = Paths.get( <span class="hljs-string">"/temp/dir1/../file.txt"</span>); </code></p>
<p>In these cases, you can use the <code>normalize()</code> method to remove redundancies like <code>.</code> and <code>..</code> (in other words, to "normalize" it):</p>
<p><code class="java hljs">Path path = Paths.get(<span class="hljs-string">"/temp/dir1/../file.txt"</span>);<br />
System.out.println(path); <span class="hljs-comment">// /temp/dir1/../file.txt</span><br />
Path path2 = path.normalize();<br />
System.out.println(path2); <span class="hljs-comment">// /temp/file.txt</span></code></p>
<p>This method does not access the file system to know if a file exists, so removing <code>..</code> and a preceding name from a path may result in a path that no longer references the original file. This can happen when that previous name is a symbolic link (a reference to another file).</p>
<p>It's better to use the <code>toRealPath()</code> method:</p>
<p><code class="java hljs"><span class="hljs-function">Path <span class="hljs-title">toRealPath</span><span class="hljs-params">(LinkOption... options)</span> <span class="hljs-keyword">throws</span> IOException</span></code></p>
<p>This method does the following:</p>
<ul>
<li>If <code>LinkOption.NOFOLLOW_LINKS</code> is passed as an argument, symbolic links are not followed (by default it does).</li>
<li>If the path is relative, it returns an absolute path.</li>
<li>It returns a <code>Path</code> with redundant elements removed (if any).</li>
</ul>
<p>We can combine two paths. There are two cases.</p>
<p>First case. If we have an absolute path and we want to combine it with a second path that doesn't have a root element (a partial path), the second path is appended:</p>
<p><code class="java hljs">Path path = Paths.get(<span class="hljs-string">"/temp"</span>);<br />
System.out.println(path.resolve(<span class="hljs-string">"newDir"</span>)); <span class="hljs-comment">// /temp/newDir</span></code></p>
<p>Second case. If we have a partial or relative path, and we want to combine it with an absolute path, this absolute path is returned:</p>
<p><code class="java hljs">Path path = Paths.get(<span class="hljs-string">"newDir"</span>);<br />
System.out.println(path.resolve(<span class="hljs-string">"/temp"</span>)); <span class="hljs-comment">// /temp</span></code></p>
<p><code>relativize()</code> is another interesting method.</p>
<p><code>path1.relativize(path2)</code> is like saying <i>give me a path that shows how to get from path1 to path2</i>.</p>
<p>For example, if we are in directory <code>/temp</code> and we want to go to <code>/temp/dir1/subdir</code>, we have to go first to dir1 and then to subdir:</p>
<p><code class="java hljs">Path path1 = Paths.get(<span class="hljs-string">"temp"</span>);<br />
Path path2 = Paths.get(<span class="hljs-string">"temp/dir1/file.txt"</span>);<br />
Path path1ToPath2 = path1.relativize(path2); <span class="hljs-comment">// dir1/file.txt</span></code></p>
<p>If the paths represent two relatives paths without any other information, they are considered siblings, so you have to go to the parent directory and then go to the other directory:</p>
<p><code class="java hljs">Path path1 = Paths.get(<span class="hljs-string">"dir1"</span>);<br />
Path path1ToPath2 = path1.relativize(Paths.get(<span class="hljs-string">"dir2"</span>)); <span class="hljs-comment">// ../dir2</span></code></p>
<p>Notice that both examples use relative paths.</p>
<p>If one of the paths is an absolute path, a relative path cannot be constructed because of the lack of information and a <code>llegalArgumentException</code> will be thrown.</p>
<p>If both paths are absolute, the result is system-dependent.</p>
<p><code>Path</code> extends the <code>Iterable</code> interface so you can do something like this:</p>
<p><code class="java hljs">Path path = Paths.get(<span class="hljs-string">"c:\\temp\\dir1\\file.txt"</span>);<br />
<span class="hljs-keyword">for</span>(Path name : path) {<br />
System.out.println(name);<br />
}</code></p>
<p>The output:</p>
<p><code class="hljs">temp<br />
dir1<br />
file.txt</code></p>
<p><code>Path</code> extends the <code>Comparable</code> interface and the <code>equals()</code> method to test two paths for equality.</p>
<p><code>compareTo()</code> compares two paths lexicographically. It returns:</p>
<ul>
<li>Zero if the argument is equal to the path,</li>
<li>A value less than zero if this path is lexicographically less than the argument, or</li>
<li>A value greater than zero if this path is lexicographically greater than the argument.</li>
</ul>
<p>The <code>equals()</code> implementation is system-dependent (for example, it's case insensitive on Windows systems). However, it returns <code>false</code> if the argument is not a <code>Path</code> or if it belongs to a different file system.</p>
<p>In addition, the methods <code>startsWith()</code> and <code>endsWith()</code> both test whether a path begins or ends with some <code>String</code> (in this case, the methods return <code>true</code> only if the string represents an actual element) or <code>Path</code>. So given:</p>
<p><code class="java hljs">Path absPath = Paths.get(<span class="hljs-string">"c:\\temp\\dir1\\file.txt"</span>);<br />
Path relPath = Paths.get(<span class="hljs-string">"temp\\dir1\\file.txt"</span>);</code></p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">boolean</span> <span class="hljs-title">startsWith</span><span class="hljs-params">(Path other)</span></span><br />
absPath.<span class="hljs-title">startsWith</span><span class="hljs-params">(Paths.get(<span class="hljs-string">"c:\\temp\\file.txt"</span>)</span>); <span class="hljs-comment">// false</span><br />
absPath.startsWith(Paths.get(<span class="hljs-string">"c:\\temp\\dir1\\img.jpg"</span>)); <span class="hljs-comment">// false</span><br />
absPath.startsWith(Paths.get(<span class="hljs-string">"c:\\temp\\dir1\\"</span>)) <span class="hljs-comment">// true</span><br />
absPath.startsWith(relPath); <span class="hljs-comment">// false</span><br />
<span class="hljs-function"><span class="hljs-keyword"><br />
boolean</span> <span class="hljs-title">startsWith</span><span class="hljs-params">(String other)</span><br />
relPath.startsWith<span class="hljs-params">(<span class="hljs-string">"t"</span>)</span></span>; <span class="hljs-comment">// false</span><br />
relPath.startsWith(<span class="hljs-string">"temp"</span>); <span class="hljs-comment">// true</span><br />
relPath.startsWith(<span class="hljs-string">"temp\\d"</span>); <span class="hljs-comment">// false</span><br />
relPath.startsWith(<span class="hljs-string">"temp\\dir1"</span>); <span class="hljs-comment">// true</span><br />
<span class="hljs-function"><span class="hljs-keyword"><br />
boolean</span> <span class="hljs-title">endsWith</span><span class="hljs-params">(Path other)</span><br />
absPath.endsWith<span class="hljs-params">(<span class="hljs-string">"file.txt"</span>)</span></span>; <span class="hljs-comment">// true</span><br />
absPath.endsWith(<span class="hljs-string">"d:\\temp\\dir1\\file.txt"</span>); <span class="hljs-comment">// false</span><br />
relPath.endsWith(absPath); <span class="hljs-comment">// false</span><br />
<span class="hljs-function"><span class="hljs-keyword"><br />
boolean</span> <span class="hljs-title">endsWith</span><span class="hljs-params">(String other)</span><br />
relPath.endsWith<span class="hljs-params">(<span class="hljs-string">"txt"</span>)</span></span>; <span class="hljs-comment">// false</span><br />
relPath.endsWith(<span class="hljs-string">"file.txt"</span>); <span class="hljs-comment">// true</span><br />
relPath.endsWith(<span class="hljs-string">"\\dir1\\file.txt"</span>); <span class="hljs-comment">// false</span><br />
relPath.endsWith(<span class="hljs-string">"dir1\\file.txt"</span>); <span class="hljs-comment">// true</span></code></p>
<p>These methods don't take into account trailing separators, so if we have the <code>Path</code> <code>temp/dir1</code>, invoking, for example, <code>endsWith()</code> with <code>dir1/</code>, it returns <code>true</code>.</p>
<h2>The Files class</h2>
<p>The <code>java.nio.file.Files</code> class has <code>static</code> methods for common operations on files and directories. In contrast with the <code>java.io.File</code> class, all methods of <code>Files</code> work with <code>Path</code> objects (so don't confuse <code>File</code> and <code>Files</code>).</p>
<p>For example, we can check if a path actually exists (or doesn't exist) with the methods:</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">exists</span><span class="hljs-params">(Path path, LinkOption... options)</span><br />
<span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">notExists</span><span class="hljs-params">(Path path, LinkOption... options)</span></span></code></p>
<p>If <code>LinkOption.NOFOLLOW_LINKS</code> is present, symbolic links are not followed (by default they are).</p>
<p>We can check if a path is readable (it's not if the file doesn't exist or if the JVM doesn't have the privileges to access it):</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isReadable</span><span class="hljs-params">(Path path)</span></span></code></p>
<p>We can check if a path is writable (it's not if the file doesn't exist or if the JVM doesn't have the privileges to access it):</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isWritable</span><span class="hljs-params">(Path path)</span></span></code></p>
<p>We can check if a file exists and is executable:</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isExecutable</span><span class="hljs-params">(Path path)</span></span></code></p>
<p>Or even check if two paths refer to the same file (useful if one path represents a symbolic link). If both <code>Path</code> objects are equal then this method returns <code>true</code> without checking if the file exists:</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isSameFile</span><span class="hljs-params">(Path path,<br />
Path path2)</span> <span class="hljs-keyword">throws</span> IOException</span></code></p>
<p>To read a file, we can load the entire file into memory (only useful for small files) with the methods:</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">byte</span>[] <span class="hljs-title">readAllBytes</span><span class="hljs-params">(Path path)</span><br />
<span class="hljs-keyword"> throws</span> IOException<br />
<span class="hljs-keyword">static</span> List<String> <span class="hljs-title">readAllLines</span><span class="hljs-params">(Path path)</span><br />
<span class="hljs-keyword"> throws</span> IOException<br />
<span class="hljs-keyword">static</span> List<String> <span class="hljs-title">readAllLines</span><span class="hljs-params">(Path path, Charset cs)</span><br />
<span class="hljs-keyword"> throws</span> IOException</span></code></p>
<p>For example:</p>
<p><code class="java hljs"><span class="hljs-keyword">try</span> {<br />
<span class="hljs-comment"> // By default it uses StandardCharsets.UTF_8</span><br />
List<String> lines = Files.readAllLines(<br />
Paths.get(<span class="hljs-string">"file.txt"</span>));<br />
lines.forEach(System.out::println); }<br />
} <span class="hljs-keyword">catch</span> (IOException e) { <span class="hljs-comment">/** */</span> }</code></p>
<p>Or to read a file in an efficient way:</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> BufferedReader <span class="hljs-title">newBufferedReader</span><span class="hljs-params">(Path path)</span><br />
<span class="hljs-keyword"> throws</span> IOException<br />
<span class="hljs-keyword">static</span> BufferedReader <span class="hljs-title">newBufferedReader</span><span class="hljs-params">(Path path, Charset cs)</span><br />
<span class="hljs-keyword"> throws</span> IOException</span></code></p>
<p>For example:</p>
<p><code class="java hljs">Path path = Paths.get(<span class="hljs-string">"/temp/dir1/files.txt"</span>);<br />
<span class="hljs-comment">// By default it uses StandardCharsets.UTF_8</span><br />
<span class="hljs-keyword">try</span> (BufferedReader reader = Files.newBufferedReader(path,<br />
StandardCharsets.ISO_8859_1)) {<br />
String line = <span class="hljs-keyword">null</span>;<br />
<span class="hljs-keyword"> while</span>((line = reader.readLine()) != <span class="hljs-keyword">null</span>)<br />
System.out.println(line);<br />
} <span class="hljs-keyword">catch</span> (IOException e) { <span class="hljs-comment">/** ... */</span> }</code></p>
<p>The <code>Files</code> class has two methods to delete files/directories.</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">delete</span><span class="hljs-params">(Path path)</span> <span class="hljs-keyword">throws</span> IOException</span></code></p>
<p>It removes the file/directory or throws an exception if something fails:</p>
<p><code class="java hljs"><span class="hljs-keyword">try</span> {<br />
Files.delete(Paths.get(<span class="hljs-string">"/temp/dir1/file.txt"</span>));<br />
Files.delete(Paths.get(<span class="hljs-string">"/temp/dir1"</span>));<br />
} <span class="hljs-keyword">catch</span> (NoSuchFileException nsfe) {<br />
<span class="hljs-comment"> // If the file/directory doesn't exists</span><br />
} <span class="hljs-keyword">catch</span> (DirectoryNotEmptyException dnee) {<br />
<span class="hljs-comment"> // To delete a directory, it must be empty,</span><br />
<span class="hljs-comment"> // otherwise, this exception is thrown</span><br />
} <span class="hljs-keyword">catch</span> (IOException ioe) {<br />
<span class="hljs-comment"> // File permission or other problems</span><br />
}</code></p>
<p>The second method is:</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">deleteIfExists</span><span class="hljs-params">(Path path)</span> <span class="hljs-keyword">throws</span> IOException</span></code></p>
<p>This method returns <code>true</code> if the file was deleted or false if the file could not be removed because it did not exist, in other words, unlike the first method, this doesn't throw a <code>NoSuchFileException</code> (but it still throws a <code>DirectoryNotEmptyException</code> and an <code>IOException</code> for other problems):</p>
<p><code class="java hljs"><span class="hljs-keyword">try</span> {<br />
Files.deleteIfExists(Paths.get(<span class="hljs-string">"/temp/dir1/file.txt"</span>));<br />
} <span class="hljs-keyword">catch</span> (DirectoryNotEmptyException dnee) {<br />
<span class="hljs-comment"> // To delete a directory, it must be empty,</span><br />
} <span class="hljs-keyword">catch</span> (IOException ioe) {<br />
<span class="hljs-comment"> // File permission or other problems</span><br />
}</code></p>
<p>To copy files/directories, we have the method:</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> Path <span class="hljs-title">copy</span><span class="hljs-params">(Path source, Path target,<br />
CopyOption... options)</span> <span class="hljs-keyword">throws</span> IOException</span></code></p>
<p>It returns the path to the target file, and when copying a directory, its content won't be copied.</p>
<p>By default, the copy fails if the destination file already exists. Also, file attributes won't be copied, and when copying a symbolic link, its target will be copied.</p>
<p>We can customize this behavior with the following <code>CopyOption</code> enums:</p>
<ul>
<li><b>StandardCopyOption.REPLACE_EXISTING</b><br /> Performs the copy when the target already exists. If the target is a symbolic link, the link itself is copied and If the target is a non-empty directory, a <code>FileAlreadyExistsException</code> is thrown.</li>
<li><b>StandardCopyOption.COPY_ATTRIBUTES</b><br /> Copies the file attributes associated with the file to the target file. The exact attributes supported are file system and platform dependent, except for last-modified-time, which is supported across platforms.</li>
<li><b>LinkOption.NOFOLLOW_LINKS</b><br /> Indicates that symbolic links should not be followed, just copied.</li>
</ul>
<p>Here's an example:</p>
<p><code class="java hljs"><span class="hljs-keyword">import</span> <span class="hljs-keyword">static</span> java.nio.file.StandardCopyOption. REPLACE_EXISTING;<br />
...<br />
<span class="hljs-keyword">try</span> {<br />
Files.copy(Paths.get(<span class="hljs-string">"in.txt"</span>),<br />
Paths.get(<span class="hljs-string">"out.txt"</span>),<br />
REPLACE_EXISTING);<br />
} <span class="hljs-keyword">catch</span> (IOException e) { <span class="hljs-comment">/** ... */</span> }</code></p>
<p>There are methods to copy between a stream and a <code>Path</code> also:</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">long</span> <span class="hljs-title">copy</span><span class="hljs-params">(InputStream in, Path target,<br />
CopyOption... options)</span> <span class="hljs-keyword">throws</span> IOException</span></code></p>
<p>Copies all bytes from an input stream to a file. By default, the copy fails if the target already exists or is a symbolic link. If the <code>StandardCopyOption.REPLACE_EXISTING</code> option is specified, and the target file already exists, then it is replaced if it's not a non-empty directory. If the target file exists and is a symbolic link, then the symbolic link is replaced. Actually, in Java 8, the <code>REPLACE_EXISTING</code> option is the only option required to be supported by this method.</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">long</span> <span class="hljs-title">copy</span><span class="hljs-params">(Path source,<br />
OutputStream out)</span> <span class="hljs-keyword">throws</span> IOException</span></code></p>
<p>Copies all bytes from a file to an output stream.</p>
<p>For example:</p>
<p><code class="java hljs"><span class="hljs-keyword">try</span> (InputStream in = <span class="hljs-keyword">new</span> FileInputStream(<span class="hljs-string">"in.csv"</span>);<br />
OutputStream out = <span class="hljs-keyword">new</span> FileOutputStream(<span class="hljs-string">"out.csv"</span>)) {<br />
Path path = Paths.get(<span class="hljs-string">"/temp/in.txt"</span>);<br />
<span class="hljs-comment"> // Copy stream data to a file</span><br />
Files.copy(in, path);<br />
<span class="hljs-comment"> // Copy the file data to a stream</span><br />
Files.copy(path, out);<br />
} <span class="hljs-keyword">catch</span> (IOException e) { <span class="hljs-comment">/** ... */</span> }</code></p>
<p>To move or rename a file/directory, we have the method:</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> Path <span class="hljs-title">move</span><span class="hljs-params">(Path source, Path target,<br />
CopyOption... options)</span> <span class="hljs-keyword">throws</span> IOException</span></code></p>
<p>By default, this method will follow links, throw an exception if the file already exists, and not perform an atomic move.</p>
<p>We can customize this behavior with the following <code>CopyOption</code> enums:</p>
<ul>
<li><b>StandardCopyOption.REPLACE_EXISTING</b><br /> Performs the move when the target already exists. If the target is a symbolic link, only the link itself is moved.</li>
<li><b>StandardCopyOption.ATOMIC_MOVE</b><br /> Performs the move as an atomic file operation. If the file system does not support an atomic move, an exception is thrown.</li>
</ul>
<p>This method can move a non-empty directory. However, if the target exists, trying to move a non-empty directory will throw a <code>DirectoryNotEmptyException</code>. This exception will also be thrown when trying to move a non-empty directory across a drives or partitions.</p>
<p>For example:</p>
<p><code class="java hljs"><span class="hljs-keyword">try</span> {<br />
<span class="hljs-comment"> // Move or rename dir1 to dir2</span><br />
Files.move(Paths.get(<span class="hljs-string">"c:\\temp\\dir1|"</span>),<br />
Paths.get(<span class="hljs-string">"c:\\temp\\dir2"</span>);<br />
} <span class="hljs-keyword">catch</span> (IOException e) { <span class="hljs-comment">/** ... */</span> }</code></p>
<h2>Managing metadata</h2>
<p>When talking about a file system, metadata give us information about a file or directory, like its size, permissions, creation date, etc. This information is referred as attributes, and some of them are system-dependent.</p>
<p>The <code>Files</code> class has some methods to get or set some attributes from a <code>Path</code> object:</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">long</span> <span class="hljs-title">size</span><span class="hljs-params">(Path path)</span> <span class="hljs-keyword">throws</span> IOException</span></code></p>
<p>Returns the size of a file (in bytes).</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isDirectory</span><span class="hljs-params">(Path path, LinkOption... options)</span></span></code></p>
<p>Tests whether a file is a directory.</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isRegularFile</span><span class="hljs-params">(Path path, LinkOption... options)</span></span></code></p>
<p>Tests whether a file is a regular file.</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isSymbolicLink</span><span class="hljs-params">(Path path)</span></span></code></p>
<p>Tests whether a file is a symbolic link.</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isHidden</span><span class="hljs-params">(Path path)</span> <span class="hljs-keyword">throws</span> IOException</span></code></p>
<p>Tells whether a file is considered hidden.</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> FileTime <span class="hljs-title">getLastModifiedTime</span><span class="hljs-params">(Path path,<br />
LinkOption... options)</span> <span class="hljs-keyword">throws</span> IOException<br />
<span class="hljs-keyword">static</span> Path <span class="hljs-title">setLastModifiedTime</span><span class="hljs-params">(Path path,<br />
FileTime time)</span> <span class="hljs-keyword">throws</span> IOException</span></code></p>
<p>Returns or updates a file's last modified time.</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> UserPrincipal <span class="hljs-title">getOwner</span><span class="hljs-params">(Path path,<br />
LinkOption... options)</span> <span class="hljs-keyword">throws</span> IOException<br />
<span class="hljs-keyword">static</span> Path <span class="hljs-title">setOwner</span><span class="hljs-params">(Path path,<br />
UserPrincipal owner)</span> <span class="hljs-keyword">throws</span> IOException</span></code></p>
<p>Returns or updates the owner of the file.</p>
<p>In methods that take an optional <code>LinkOption.NOFOLLOW_LINKS</code>, symbolic links are not followed (by default they are).</p>
<p>In the case of <code>getLastModifiedTime()</code> and <code>setLastModifiedTime()</code> the class <code>java.nio.file.attribute.FileTime</code> represents the value of a file's time stamp attribute.</p>
<p>We can create an instance of <code>FileTime</code> with these <code>static</code> methods:</p>
<p><code class="java hljs"><span class="hljs-function"><span class="hljs-keyword">static</span> FileTime <span class="hljs-title">from</span><span class="hljs-params">(Instant instant)<br /></span> <span class="hljs-keyword">static</span> FileTime <span class="hljs-title">from</span><span class="hljs-params">(<span class="hljs-keyword">long</span> value, TimeUnit unit)</span><br />
<span class="hljs-keyword">static</span> FileTime <span class="hljs-title">fromMillis</span><span class="hljs-params">(<span class="hljs-keyword">long</span> value)</span></span></code></p>
<p>And from a <code>FileTime</code> we can get an <code>Instant</code> or milliseconds as <code>long</code>:</p>
<p><code class="java hljs"><span class="hljs-function">Instant <span class="hljs-title">toInstant</span><span class="hljs-params">()</span><br />
<span class="hljs-keyword">long</span> <span class="hljs-title">toMillis</span><span class="hljs-params">()</span></span></code></p>
<p>For example:</p>
<p><code class="java hljs"><span class="hljs-keyword">try</span> {<br />
Path path = Paths.get(<span class="hljs-string">"/temp/dir1/file.txt"</span>);<br />
FileTime ft = Files.getLastModifiedTime(path);<br />
Files.setLastModifiedTime(path,<br />
FileTime.fromMillis(ft.toMillis + <span class="hljs-number">1000</span>)); <span class="hljs-comment">// adds a second</span><br />
} <span class="hljs-keyword">catch</span> (IOException e) { <span class="hljs-comment">/** ... */</span> }</code></p>
<p>In the case of <code>getOwner()</code> and <code>setOwner()</code> the interface <code>java.nio.file.attribute.UserPrincipal</code> is an abstract representation of an identity that can be used like this:</p>
<p><code class="java hljs"><span class="hljs-keyword">try</span> {<br />
Path path = Paths.get(<span class="hljs-string">"/temp/dir1/file.txt"</span>);<br />
<span class="hljs-comment"> // FileSystems.getDefault() also gets a FileSystem object</span><br />
UserPrincipal owner = path.getFileSystem()<br />
.getUserPrincipalLookupService()<br />
.lookupPrincipalByName(<span class="hljs-string">"jane"</span>);<br />
Files.setOwner(path, owner);<br />
} <span class="hljs-keyword">catch</span> (IOException e) { <span class="hljs-comment">/** ... */</span> }</code></p>
<p>These methods are useful to get or update a single attribute. But we can also get a group of related attributes by functionality or by a particular systems implementation as a view.</p>
<p>The three most common view classes are:</p>
<ul>
<li><b>java.nio.file.attribute.BasicFileAttributeView</b><br /> Provides a view of basic attributes supported by all file systems.</li>
<li><b>java.nio.file.attribute. DosFileAttributeView</b><br /> Extends <code>BasicFileAttributeView</code> to support additionally a set of DOS attribute flags that are used to indicate if the file is read-only, hidden, a system file, or archived.</li>
<li><b>java.nio.file.attribute. PosixFileAttributeView</b><br /> Extends <code>BasicFileAttributeView</code> with attributes supported on POSIX systems, such as Linux and Mac. Examples of these attributes are file owner, group owner, and related access permissions.</li>
</ul>
<p>You can get a file attribute view of a given type to read or update a set of attributes with the method:</p>
<p><code class="java hljs"><span class="hljs-keyword">static</span> <V extends FileAttributeView> <span class="hljs-function">V <span class="hljs-title">getFileAttributeView</span><span class="hljs-params">(<br />
Path path, Class<V> type,LinkOption... options)</span></span></code></p>
<p>For example, <code>BasicFileAttributeView</code> has only one update method:</p>
<p><code class="java hljs"><span class="hljs-keyword">try</span> {<br />
Path path = Paths.get(<span class="hljs-string">"/temp/dir/file.txt"</span>);<br />
BasicFileAttributeView view =<br />
Files.getFileAttributeView(path,<br />
BasicFileAttributeView.class);<br />
<span class="hljs-comment"> // Get a class with read-only attributes</span><br />
BasicFileAttributes readOnlyAttrs =<br />
view.readAttributes();<br />
FileTime lastModifiedTime =<br />
FileTime.from(Instant.now());<br />
FileTime lastAccessTime =<br />
FileTime.from(Instant.now());<br />
FileTime createTime =<br />
FileTime.from(Instant.now());<br />
<span class="hljs-comment"> //If any argument is null,<br />
//the corresponding value is not changed</span><br />
view.setTimes(lastModifiedTime,<br />
lastAccessTime,<br />
createTime);<br />
} <span class="hljs-keyword">catch</span> (IOException e) { <span class="hljs-comment">/** ... */</span> }</code></p>
<p>Most of the time, you'll work with the read-only versions of the file views. In this case, you can use the following method to get them directly:</p>
<p><code class="java hljs"><span class="hljs-keyword">static</span> <A extends BasicFileAttributes> <span class="hljs-function">A<br />
<span class="hljs-title"> readAttributes</span><span class="hljs-params">(Path path, Class<A> type,<br />
LinkOption... options)</span><br />
<span class="hljs-keyword"> throws</span> IOException</span></code></p>
<p>The second parameter is the return type of the method, the class that contains the attributes to use (notice that all attributes classes extend from <code>BasicFileAttributes</code> because it contains attributes common to all file systems). The third argument is when you want to follow symbolic links.</p>
<p>Here's an example of how to access the file attributes of a file using the <code>java.nio.file.attribute.BasicFileAttributes</code> class:</p>
<p><code class="java hljs"><span class="hljs-keyword">try</span> {<br />
Path path = Paths.get(<span class="hljs-string">"/temp/dir1/file.txt"</span>);<br />
BasicFileAttributes attr = Files.readAttributes(<br />
path, BasicFileAttributes.class);<br />
<span class="hljs-comment"> // Size in bytes<br /></span> System.out.println(<span class="hljs-string">"size(): "</span> + attr.size());<br />
<span class="hljs-comment"> // Unique file identifier (or null if not available)</span><br />
System.out.println(<span class="hljs-string">"fileKey(): "</span> + attr.fileKey());<br />
<br />
System.out.println(<span class="hljs-string">"isDirectory(): "</span> + attr.isDirectory());<br />
System.out.println(<span class="hljs-string">"isRegularFile(): "</span> + attr.isRegularFile());<br />
System.out.println(<span class="hljs-string">"isSymbolicLink(): "</span> + attr.isSymbolicLink());<br />
<span class="hljs-comment"> // Is something other than a file, directory, or symbolic link?</span><br />
System.out.println(<span class="hljs-string">"isOther(): "</span> + attr.isOther());<br />
<span class="hljs-comment"><br />
// The following methods return a FileTime instance</span><br />
System.out.println(<span class="hljs-string">"creationTime(): "</span> + attr.creationTime());<br />
System.out.println(<span class="hljs-string">"lastModifiedTime():"</span>+attr.lastModifiedTime());<br />
System.out.println(<span class="hljs-string">"lastAccessTime(): "</span> + attr.lastAccessTime());<br />
} <span class="hljs-keyword">catch</span> (IOException e) { <span class="hljs-comment">/** ... */</span> }</code></p>
<h2>Key Points</h2>
<ul>
<li>The primary classes of <code>java.nio.file</code> are <code>Path</code>, <code>Paths</code>, and <code>Files</code>. They are intended to be a replacement of the <code>java.io.File</code> class.</li>
<li>The <code>Path</code> interface defines an object that represents the path to a file or a directory.</li>
<li><code>java.nio.file.Paths</code> provides methods to create a <code>Path</code> object.</li>
<li>The absolute path representation of a <code>Path</code> object has a root component (either <code>c:\</code> or <code>/</code>) and a sequence of names separated by a (forward or backward) slash.</li>
<li>The <code>Path</code> interface has methods to get the elements of the path, normalize paths, and get attributes of the path (isAbsolute(), getFileSystem(), etc), among others. It also extends <code>Comparable</code> and implements <code>equals()</code> to test for equality.</li>
<li>The <code>java.nio.file.Files</code> class has static methods for common operations on files and directories. In contrast with the <code>java.io.File class</code>, all methods of <code>Files</code> work with <code>Path</code> objects.</li>
<li>Examples of these operations are checking the existence of a file, copying, moving, deleting, and reading.</li>
<li>You can also get attributes of a file individually (with methods like <code>isHidden()</code>) or in a group through views.</li>
<li>The three most common view classes are <code>BasicFileAttributeView</code>, <code>DosFileAttributeView</code>, and <code>PosixFileAttributeView</code>.</li>
<li>You can get a file attribute view of a given type to read or update a set of attributes with the method <code>getFileAttributeView()</code>.</li>
<li>You can get a class that is a read-only version of the view with the method <code>readAttributes()</code>.</li>
</ul>
<div style="page-break-after:always;"></div>
<h2>Self Test</h2>
<p>1. Given:</p>
<p><code class="java hljs">Path path1 = Paths.get(<span class="hljs-string">"/projects/work/../fun"</span>);<br />
Path path2 = Paths.get(<span class="hljs-string">"games"</span>);<br />
System.out.println(path1.resolve(path2));</code></p>
<p>Which of the following is the result of executing the above lines?<br /> A. <code>/project/work/fun/games</code><br /> B. <code>/project/fun/games</code><br /> C. <code>/project/work/../fun/games</code><br /> D. <code>games</code></p>
<div style="page-break-after:always;"></div>
<p>2. Given:</p>
<p><code class="java hljs">Path path = Paths.get(<span class="hljs-string">"c:\\Users\\mark"</span>);</code></p>
<p>Which of the following will return <code>Users</code>?<br /> A. <code>path.getRoot()</code><br /> B. <code>path.getName(0)</code><br /> C. <code>path.getName(1)</code><br /> D. <code>path.subpath(0, 0);</code></p>
<div style="page-break-after:always;"></div>
<p>3. Which of the following is not a valid <code>CopyOption</code> for <code>Files.copy()</code>?<br /> A. <code>NOFOLLOW_LINKS</code><br /> B. <code>REPLACE_EXISTING</code><br /> C. <code>ATOMIC_MOVE</code><br /> D. <code>COPY_ATTRIBUTES</code></p>
<div style="page-break-after:always;"></div>
<p>4. Given:</p>
<p><code class="java hljs">Path path =<br />
Paths.get(<span class="hljs-string">"c:\\.\\temp\\data\\..\\.\\dir\\..\\file.txt"</span>);<br />
<span class="hljs-keyword">try</span> {<br />
path = path.toRealPath();<br />
} <span class="hljs-keyword">catch</span> (IOException e) { }<br />
System.out.println(path.subpath(<span class="hljs-number">1</span>,<span class="hljs-number">2</span>));</code></p>
<p>Which is the result?<br /> A. <code>temp</code><br /> B. <code>data</code><br /> C. <code>dir</code><br /> D. <code>file.txt</code></p>
<div style="page-break-after:always;"></div>
<p>5. Which of the following is a valid way to set a file's create time?</p>
<p>A.</p>
<p><code class="java hljs">FileTime time = FileTime.from(Instance.now());<br />
Files.getFileAttributeView(path,<br />
BasicFileAttributeView.class)<br />
.setTimes(<span class="hljs-keyword">null</span>, time, <span class="hljs-keyword">null</span>);</code></p>
<p>B.</p>
<p><code class="java hljs">Files.setCreateTime(path,<br />
FileTime.from(Instance.now());</code></p>
<p>C.</p>
<p><code class="java hljs">Files.getFileAttributeView(path,<br />
BasicFileAttributeView.class)<br />
.setTimes(<span class="hljs-keyword">null</span>, <span class="hljs-keyword">null</span>, Instance.now());</code></p>
<p>D.</p>
<p><code class="java hljs">FileTime time = FileTime.from(Instance.now());<br />
Files.getFileAttributeView(path,<br />
BasicFileAttributeView.class)<br />
.setTimes(<span class="hljs-keyword">null</span>, <span class="hljs-keyword">null</span>, time);</code></p>
<div class="answers">
<a href="ch24a.html" target="_blank">Open answers page</a>
</div>
<div class="book-info"></div>
<div class="linkbox">
<div class="previous">
<a href="ch23.html">23. Java I/O Fundamentals</a>
</div>
<div class="next">
<a href="ch25.html">25. Files and Streams</a>
</div>
<div style="clear:both;"></div>
</div>
</div>
</div>
</body>
</html>