//声明:部分内容引自《Java编程思想(第四版)》机械工业出版社
【File 类】
– 目录列表器。例:
package io;//: io/DirList.java
// Display a directory listing using regular expressions.
// {Args: "D.*\.java"}
import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.regex.Pattern;
/**
* Created by JT on 2016/7/23.
*/
public class DirList {
public static void main(String[] args) {
File path = new File("."); // 创建 File 对象
String[] list; // 创建字符串数组
if (args.length == 0)
list = path.list(); // 如果指定目录为空,则 list 存储所有 path 指向的文件的文件名
else
list = path.list(new DirFilter(args[0])); // 如果指定目录不为空,则 list 存储所有 path 指向的文件中符合目录过滤器的文件的文件名
Arrays.sort(list, String.CASE_INSENSITIVE_ORDER); // 将 list 中存储的内容按字母(不区分大小写)顺序排列
for (String dirItem : list)
System.out.println(dirItem); // 输出 list 中保存的内容
}
}
class DirFilter implements FilenameFilter { // 目录过滤器
private Pattern pattern;
public DirFilter(String regex) { // 构造方法,将 pattern 初始化为正则表达式编译后的结果
pattern = Pattern.compile(regex);
}
public boolean accept(File dir, String name) { // 实现接口 FilenameFilter 中的 accept() 方法,
// 此方法必须接受一个代表某个特定文件所在目录的 File 对象,以及包含了那个文件名的一个 String。
// accept() 方法会使用一个正则表达式的 matcher 对象,来查看此正则表达式 regex 是否匹配这个文件的名字。
return pattern.matcher(name).matches();
}
}
DirFilter 是目录过滤器类,这个类存在的唯一原因就是要实现 accept() 方法。创建这个类的目的在于把 accept() 方法提供给 list() 使用,使 list() 可以回调 accept(),进而以决定哪些文件包含在列表中。因此,这种结构也常常称为回调。更具体的说,这是一个策略模式的例子,因为 list() 实现了基本的功能,而且按照 FilenameFilter 的形式提供了这个策略,以便完善 list() 在提供服务时所需的算法。因为 list() 接受 FilenameFilter 对象作为参数,这意味着我们可以传递实现了 FilenameFilter 接口的任何类的对象,用以选择(甚至在运行时)list() 方法的行为方式。策略的目的就是提供了代码行为的灵活性。
list() 方法会为此目录对象下的每一个文件名调用 accept(),来判断该文件是否包含在内,判断结果由 accept() 返回的布尔值表示。
【输入和输出】
– 存储和恢复数据。
例:
package io;//: io/StoringAndRecoveringData.java
import java.io.*;
/**
* Created by JT on 2016/7/24.
*/
public class StoringAndRecoveringData {
public static void main(String[] args) throws IOException {
DataOutputStream out = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream("Data.txt")
)
);
out.writeDouble(3.14159);
out.writeUTF("That was pi");
out.writeDouble(1.41413);
out.writeUTF("Square root of 2");
out.close();
DataInputStream in = new DataInputStream(
new BufferedInputStream(
new FileInputStream("Data.txt")
)
);
System.out.println(in.readDouble());
// Only readUTF() will recover the
// Java-UTF String properly:
System.out.println(in.readUTF());
System.out.println(in.readDouble());
System.out.println(in.readUTF());
}
}
PrintWriter 可以对数据进行格式化,以便人们的阅读。但是为了输出可供另一个“流”恢复的数据,我们需要用 DataOutputStream 写入数据,并用 DataInputStream 恢复数据。当然,这些流可以是任意形式,但该例使用的是一个文件,并且对于读和写都进行了缓冲处理。(因为 DataOutputStream 和 DataInputStream 是面向字节的,所以要使用 InputStream 和 OutputStream。)
如果我们使用 DataInputStream 写入数据,Java 保证我们可以使用 DataInputStream 准确地读取数据——无论读和写数据的平台多么不同。
【标准 I/O】
– 程序的所有输入都可以来自于标准输入,它的所有输出也都可以发送到标准输出,以及所有的错误信息都可以发送到标准错误。标准 I/O 的意义在于:我们可以很容易地把程序串联起来,一个程序的标准输出可以成为另一程序的标准输入。
– 从标准输入中读取。
按照标准 I/O 模型,Java提供了 System.in、System.out、System.err。其中 System.out 和 System.err 已经事先被包装成了 printStream 对象,所以可以立即使用。System.in 是一个没有被包装过的未经加工的 InputStream,因此读取 System.in 之前必须对其进行包装。
例(直接回显输入的每一行):
通常,我们会用 readLine() 一次一行地读取输入,为此,我们将 System.in 包装成 BufferedReader 来使用,这要求我们必须用 InputStreamReader 把 System.in 转换成 Reader。
package io;//: io/Echo.java
// How to read from standard input.
// {RunByHand}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* Created by JT on 2016/7/24.
*/
public class Echo {
public static void main(String[] args) throws IOException {
BufferedReader stdin = new BufferedReader(
new InputStreamReader(System.in)
);
String s;
while ((s = stdin.readLine()) != null && s.length()!=0)
System.out.println(s);
}
}
– 将 System.out 转换成 PrintWriter。、
Sytem.out 是一个 PrintStream, 而 PrintStream 是一个 OutputStream。PrintWriter 有一个可以接受 OutputStream 作为参数的构造器。因此,只要需要,就可以使用那个构造器把 System.out 转换成 PrintWriter。
例:
package io;//: io/ChangeSystemOut.java
// Turn System.out.PrintWriter.
import java.io.PrintWriter;
/**
* Created by JT on 2016/7/24.
*/
public class ChangeSystemOut {
public static void main(String[] args) {
PrintWriter out = new PrintWriter(System.out, true);
out.println("Hello, world");
}
}
重要的是要使用有两个参数的 PrintWriter 的构造器,并将第二个参数设为 true,以便开启自动清空功能,否则,你可能看不到输出。
– 标准 I/O 重定向。
如果我们突然开始在显示器上创建大量输出,而这些输出滚动得太快以至于无法阅读时,重定向输出就显得极为有用。
例:
package io;//: io/Redirecting.java
// Demonstrates standard I/O redirection.
import java.io.*;
/**
* Created by JT on 2016/7/24.
*/
public class Redirecting {
public static void main(String[] args) throws IOException {
PrintStream console = System.out;
BufferedInputStream in = new BufferedInputStream(
new FileInputStream("Redirecting.java")
);
PrintStream out = new PrintStream(
new BufferedOutputStream(
new FileOutputStream("test.out")
)
);
System.setIn(in);
System.setOut(out);
System.setErr(out);
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
String s;
while ((s = br.readLine()) != null)
System.out.println(s);
out.close(); // Remember this!
System.setOut(console);
}
}
这个程序将标准输入附接到文件上,并将标准输出和标准错误重定向到另一个文件。其中注意,它在程序开头处存储了对最初的 System.out 对象的引用,并且在结尾处将系统输出恢复到了该对象上。
I/O 重定向操纵的是字节流,而不是字符流,因此我们使用的是 InputStream 和 OutoutStream,而不是 Reader 和 Writer。