Thinking in Java 第18章 Java I/O 系统(18.1-18.8)

来源:互联网 发布:淘宝卖家工具箱下载 编辑:程序博客网 时间:2024/05/22 13:47

//声明:部分内容引自《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.javaimport 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。

0 0
原创粉丝点击