Skip to content

Commit a4a0995

Browse files
committed
first commit on CP 17.1
1 parent 9f9b8e4 commit a4a0995

File tree

2 files changed

+298
-2
lines changed

2 files changed

+298
-2
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,6 @@ _book
2020
._*
2121
*/.DS_Store
2222
*/._*
23+
24+
# IDEA
25+
/.idea/*

docs/book/17-Files.md

+295-2
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,310 @@
22

33
<!-- File -->
44
# 第十七章 文件
5+
在丑陋的Java I/O编程方式诞生多年以后,Java终于简化了文件读写的基本操作。这种"困难方式"的全部细节都在[Appendix: I/O Streams]()。如果你读过这个部分,就会认同Java设计者毫不在意他们的使用者的体验这一观念。打开并读取文件对于大多数编程语言来是非常常用的,由于I/O糟糕的设计以至于
6+
很少有人能够在不依赖其他参考代码的情况下完成打开文件的操作。
57

8+
好像Java设计者终于意识到了Java使用者多年来的痛苦,在Java7中对此引入了巨大的改进。这些新元素被放在**java.nio.file**包下面,过去人们通常把**nio**中的**n**理解为**new**即新的**io**,现在更应该当成是**non-blocking**非阻塞**io**(**io**就是*input/output输入/输出*)。**java.nio.file**库终于将Java文件操作带到与其他编程语言相同的水平。最重要的是Java8新增的streams与文件结合使得文件操作编程变得更加优雅。我们将看一下文件操作的两个基本组件:
9+
1. 文件或者目录的路径;
10+
2. 文件本身。
611

712
<!-- File and Directory Paths -->
813
## 文件和目录路径
14+
### `Paths`
15+
一个**Path**对象表示一个文件或者目录的路径,是一个跨操作系统(OS)和文件系统的抽象,目的是在构造路径时不必关注底层操作系统,代码可以在不进行修改的情况下运行在不同的操作系统上。**java.nio.file.Paths**类包含一个重载方法**static get()**,该方法方法接受一系列**Strings**字符串或一个*统一资源标识符*(URI)作为参数,并且进行转换返回一个**Path**对象:
16+
```java
17+
// files/PathInfo.java
18+
import java.nio.file.*;
19+
import java.net.URI;
20+
import java.io.File;
21+
import java.io.IOException;
922

23+
public class PathInfo {
24+
static void show(String id, Object p) {
25+
System.out.println(id + ": " + p);
26+
}
27+
28+
static void info(Path p) {
29+
show("toString", p);
30+
show("Exists", Files.exists(p));
31+
show("RegularFile", Files.isRegularFile(p));
32+
show("Directory", Files.isDirectory(p));
33+
show("Absolute", p.isAbsolute());
34+
show("FileName", p.getFileName());
35+
show("Parent", p.getParent());
36+
show("Root", p.getRoot());
37+
System.out.println("******************");
38+
}
39+
public static void main(String[] args) {
40+
System.out.println(System.getProperty("os.name"));
41+
info(Paths.get("C:", "path", "to", "nowhere", "NoFile.txt"));
42+
Path p = Paths.get("PathInfo.java");
43+
info(p);
44+
Path ap = p.toAbsolutePath();
45+
info(ap);
46+
info(ap.getParent());
47+
try {
48+
info(p.toRealPath());
49+
} catch(IOException e) {
50+
System.out.println(e);
51+
}
52+
URI u = p.toUri();
53+
System.out.println("URI: " + u);
54+
Path puri = Paths.get(u);
55+
System.out.println(Files.exists(puri));
56+
File f = ap.toFile(); // Don't be fooled
57+
}
58+
}
1059

11-
<!-- Directories -->
12-
## 目录
60+
/* 输出:
61+
Windows 10
62+
toString: C:\path\to\nowhere\NoFile.txt
63+
Exists: false
64+
RegularFile: false
65+
Directory: false
66+
Absolute: true
67+
FileName: NoFile.txt
68+
Parent: C:\path\to\nowhere
69+
Root: C:\
70+
******************
71+
toString: PathInfo.java
72+
Exists: true
73+
RegularFile: true
74+
Directory: false
75+
Absolute: false
76+
FileName: PathInfo.java
77+
Parent: null
78+
Root: null
79+
******************
80+
toString: C:\Users\Bruce\Documents\GitHub\onjava\
81+
ExtractedExamples\files\PathInfo.java
82+
Exists: true
83+
RegularFile: true
84+
Directory: false
85+
Absolute: true
86+
FileName: PathInfo.java
87+
Parent: C:\Users\Bruce\Documents\GitHub\onjava\
88+
ExtractedExamples\files
89+
Root: C:\
90+
******************
91+
toString: C:\Users\Bruce\Documents\GitHub\onjava\
92+
ExtractedExamples\files
93+
Exists: true
94+
RegularFile: false
95+
Directory: true
96+
Absolute: true
97+
FileName: files
98+
Parent: C:\Users\Bruce\Documents\GitHub\onjava\
99+
ExtractedExamples
100+
Root: C:\
101+
******************
102+
toString: C:\Users\Bruce\Documents\GitHub\onjava\
103+
ExtractedExamples\files\PathInfo.java
104+
Exists: true
105+
RegularFile: true
106+
Directory: false
107+
Absolute: true
108+
FileName: PathInfo.java
109+
Parent: C:\Users\Bruce\Documents\GitHub\onjava\
110+
ExtractedExamples\files
111+
Root: C:\
112+
******************
113+
URI: file:///C:/Users/Bruce/Documents/GitHub/onjava/
114+
ExtractedExamples/files/PathInfo.java
115+
true
116+
*/
117+
```
118+
119+
我已经在这一章第一个程序的**main()**方法添加了第一行用于展示操作系统的名称,因此你可以看到不同操作系统之间存在哪些差异。理想情况下,差别会相对较小,并且使用**/**或者**\\**路径分隔符进行分隔。你可以看到我运行在Windows 10上的程序输出。
120+
121+
**toString()**方法生成完整形式的路径,你可以看到**getFileName()** 方法总是返回当前文件名。
122+
通过使用**Files**工具类(我们接下类将会更多的使用它),可以测试一个文件是否存在,测试是否是一个"真正"的文件还是一个目录等等。"Nofile.txt"这个示例展示我们描述的文件可能并不在指定的位置;这样可以允许你创建一个新的路径。"PathInfo.java"存在于当前目录中,最初它只是没有路径的文件名,但它仍然被检测为"存在"。一旦我们将其转换为绝对路径,我们将会得到一个从"C:"盘(因为我们是在Windows机器下进行测试)开始的完整路径,现在它也拥有一个父路径。“真实”路径的定义在文档中有点模糊
123+
因为它取决于具体的文件系统。例如,如果文件名不区分大小写,即使路径由于大小写的缘故而不是完全相同,也可能得到肯定的匹配结果。
124+
125+
```java
126+
// files/PartsOfPaths.java
127+
import java.nio.file.*;
128+
129+
public class PartsOfPaths {
130+
public static void main(String[] args) {
131+
System.out.println(System.getProperty("os.name"));
132+
Path p = Paths.get("PartsOfPaths.java").toAbsolutePath();
133+
for(int i = 0; i < p.getNameCount(); i++)
134+
System.out.println(p.getName(i));
135+
System.out.println("ends with '.java': " +
136+
p.endsWith(".java"));
137+
for(Path pp : p) {
138+
System.out.print(pp + ": ");
139+
System.out.print(p.startsWith(pp) + " : ");
140+
System.out.println(p.endsWith(pp));
141+
}
142+
System.out.println("Starts with " + p.getRoot() + " " + p.startsWith(p.getRoot()));
143+
}
144+
}
145+
146+
/* 输出:
147+
Windows 10
148+
Users
149+
Bruce
150+
Documents
151+
GitHub
152+
on-java
153+
ExtractedExamples
154+
files
155+
PartsOfPaths.java
156+
ends with '.java': false
157+
Users: false : false
158+
Bruce: false : false
159+
Documents: false : false
160+
GitHub: false : false
161+
on-java: false : false
162+
ExtractedExamples: false : false
163+
files: false : false
164+
PartsOfPaths.java: false : true
165+
Starts with C:\ true
166+
*/
167+
```
168+
169+
```java
170+
// files/PathAnalysis.java
171+
import java.nio.file.*;
172+
import java.io.IOException;
13173

174+
public class PathAnalysis {
175+
static void say(String id, Object result) {
176+
System.out.print(id + ": ");
177+
System.out.println(result);
178+
}
179+
180+
public static void main(String[] args) throws IOException {
181+
System.out.println(System.getProperty("os.name"));
182+
Path p = Paths.get("PathAnalysis.java").toAbsolutePath();
183+
say("Exists", Files.exists(p));
184+
say("Directory", Files.isDirectory(p));
185+
say("Executable", Files.isExecutable(p));
186+
say("Readable", Files.isReadable(p));
187+
say("RegularFile", Files.isRegularFile(p));
188+
say("Writable", Files.isWritable(p));
189+
say("notExists", Files.notExists(p));
190+
say("Hidden", Files.isHidden(p));
191+
say("size", Files.size(p));
192+
say("FileStore", Files.getFileStore(p));
193+
say("LastModified: ", Files.getLastModifiedTime(p));
194+
say("Owner", Files.getOwner(p));
195+
say("ContentType", Files.probeContentType(p));
196+
say("SymbolicLink", Files.isSymbolicLink(p));
197+
if(Files.isSymbolicLink(p))
198+
say("SymbolicLink", Files.readSymbolicLink(p));
199+
if(FileSystems.getDefault().supportedFileAttributeViews().contains("posix"))
200+
say("PosixFilePermissions",
201+
Files.getPosixFilePermissions(p));
202+
}
203+
}
14204

205+
/* 输出:
206+
Windows 10
207+
Exists: true
208+
Directory: false
209+
Executable: true
210+
Readable: true
211+
RegularFile: true
212+
Writable: true
213+
notExists: false
214+
Hidden: false
215+
size: 1631
216+
FileStore: SSD (C:)
217+
LastModified: : 2017-05-09T12:07:00.428366Z
218+
Owner: MINDVIEWTOSHIBA\Bruce (User)
219+
ContentType: null
220+
SymbolicLink: false
221+
*/
222+
```
223+
224+
```java
225+
// files/AddAndSubtractPaths.java
226+
import java.nio.file.*;
227+
import java.io.IOException;
228+
229+
public class AddAndSubtractPaths {
230+
static Path base = Paths.get("..", "..", "..").toAbsolutePath().normalize();
231+
232+
static void show(int id, Path result) {
233+
if(result.isAbsolute())
234+
System.out.println("(" + id + ")r " + base.relativize(result));
235+
else
236+
System.out.println("(" + id + ") " + result);
237+
try {
238+
System.out.println("RealPath: " + result.toRealPath());
239+
} catch(IOException e) {
240+
System.out.println(e);
241+
}
242+
}
243+
244+
public static void main(String[] args) {
245+
System.out.println(System.getProperty("os.name"));
246+
System.out.println(base);
247+
Path p = Paths.get("AddAndSubtractPaths.java").toAbsolutePath();
248+
show(1, p);
249+
Path convoluted = p.getParent().getParent()
250+
.resolve("strings").resolve("..")
251+
.resolve(p.getParent().getFileName());
252+
show(2, convoluted);
253+
show(3, convoluted.normalize());
254+
Path p2 = Paths.get("..", "..");
255+
show(4, p2);
256+
show(5, p2.normalize());
257+
show(6, p2.toAbsolutePath().normalize());
258+
Path p3 = Paths.get(".").toAbsolutePath();
259+
Path p4 = p3.resolve(p2);
260+
show(7, p4);
261+
show(8, p4.normalize());
262+
Path p5 = Paths.get("").toAbsolutePath();
263+
show(9, p5);
264+
show(10, p5.resolveSibling("strings"));
265+
show(11, Paths.get("nonexistent"));
266+
}
267+
}
268+
269+
/* 输出:
270+
Windows 10
271+
C:\Users\Bruce\Documents\GitHub
272+
(1)r onjava\
273+
ExtractedExamples\files\AddAndSubtractPaths.java
274+
RealPath: C:\Users\Bruce\Documents\GitHub\onjava\
275+
ExtractedExamples\files\AddAndSubtractPaths.java
276+
(2)r on-java\ExtractedExamples\strings\..\files
277+
RealPath: C:\Users\Bruce\Documents\GitHub\onjava\
278+
ExtractedExamples\files
279+
(3)r on-java\ExtractedExamples\files
280+
RealPath: C:\Users\Bruce\Documents\GitHub\onjava\
281+
ExtractedExamples\files
282+
(4) ..\..
283+
RealPath: C:\Users\Bruce\Documents\GitHub\on-java
284+
(5) ..\..
285+
RealPath: C:\Users\Bruce\Documents\GitHub\on-java
286+
(6)r on-java
287+
RealPath: C:\Users\Bruce\Documents\GitHub\on-java
288+
(7)r on-java\ExtractedExamples\files\.\..\..
289+
RealPath: C:\Users\Bruce\Documents\GitHub\on-java
290+
(8)r on-java
291+
RealPath: C:\Users\Bruce\Documents\GitHub\on-java
292+
(9)r on-java\ExtractedExamples\files
293+
RealPath: C:\Users\Bruce\Documents\GitHub\onjava\
294+
ExtractedExamples\files
295+
(10)r on-java\ExtractedExamples\strings
296+
RealPath: C:\Users\Bruce\Documents\GitHub\onjava\
297+
ExtractedExamples\strings
298+
(11) nonexistent
299+
java.nio.file.NoSuchFileException:
300+
C:\Users\Bruce\Documents\GitHub\onjava\
301+
ExtractedExamples\files\nonexistent
302+
*/
303+
```
15304
<!-- File Systems -->
305+
306+
<!-- Directories -->
307+
## 目录
308+
16309
## 文件系统
17310

18311

0 commit comments

Comments
 (0)