IO 基础

作者: SingleDiego | 来源:发表于2018-03-21 15:03 被阅读6次

    计算机最重要的功能是处理数据。一个有用的计算机语言需要拥有良好的 IO 功能,以便让未处理的数据流入程序,让已处理的数据流出。

    与其他语言相比,Java 的 IO 功能显得复杂。在其他语言中,许多 IO 功能(比如读取文件),是被封装好的,可以用一两行程序实现。在 Java 中,程序员往往需要多个层次的装饰(decoration),才能实现文件读取。

    相对的复杂性带来的好处是 IO 的灵活性。在 Java 中,程序员可以控制 IO 的整个流程,从而设计出最好的 IO 方式。我们将在下文看到更多。




    IO 示例

    新建一个文件 file.txt,把它放在和 Test.java 同一个文件夹下。

    写入以下内容:

    Hello World!
    Hello Nerd!
    

    我们在 Test.java 来读取它:

    import java.io.*;
    
    public class Test
    {
        public static void main(String[] args)
        {
            try {
                // 读取文件,创建 br 对象
                BufferedReader br = 
                    new BufferedReader(new FileReader("file.txt")); 
    
                // 逐行读取
                String line = br.readLine();
    
                // 用一个循环输出读取到的内容,完成后关闭
                while (line != null) {
                    System.out.println(line);
                    line = br.readLine();
                }
                br.close();
            }
            catch(IOException e) {
                System.out.println("IO Problem");
            }
        }
    }
    

    这将输出 file.txt 里的内容,如果读取发生错误(如 file.txt 不存在,错误将会被捕获,抛出 IO Problem)。




    装饰器与功能组合

    程序 IO 的关键在于创建 BufferedReader 对象 br

    BufferedReader br = new BufferedReader(new FileReader("file.txt"));
    

    在创建的过程中,我们先建立了一个 FileReader 对象,这个对象的功能是从文件 "file.txt" 中读取字节(byte)流,并转换为文本流。

    在 Java 中,标准的文本编码方式为 unicode。BufferedReader() 接收该 FileReader 对象,并拓展 FileReader 的功能,新建出一个 BufferedReader 对象。

    该对象除了有上述的文件读取和转换的功能外,还提供了 缓存读取(buffered)的功能。最后,我们通过对 br 对象调用readLine() 方法,可以逐行的读取文件。

    缓存读取是在内存中开辟一片区域作为缓存,该区域存放 FileReader 读出的文本流。当该缓存的内容被读走后(比如 readLine() 命令),缓存会加载后续的文本流。

    BufferedReader() 是一个 装饰器(decorator),它接收一个原始的对象,并返回一个经过装饰的、功能更复杂的对象。修饰器的好处是,它可以用于修饰不同的对象。我们这里被修饰的是从文件中读取的文本流。其他的文本流,比如标准输入,网络传输的流等等,都可以被 BufferedReader() 修饰,从而实现缓存读取。




    更多的组合

    事实上,Java 提供了丰富的装饰器。FileReader 中合并了读取和转换两个步骤,并采用了常用的默认设置,比如编码采取 unicode。

    我们可以使用 FileInputStream + InputStreamReader 的组合来替代 FileReader,从而分离读取字节和转换两个步骤,并对两个过程有更好的控制。

    当然,FileReader 的使用更加方便。InputStreamReader 是将 FileInputStream 转换成一个 Reader,用于处理 unicode 文本。

    箭头表示数据流动方向

    流的读写来自于四个基类:InputStreamOutputStreamReaderWriter

    InputStreamReader 是处理读取操作,OutputStreamWriter 是处理写入操作。它们都位于 java.io 包中。继承关系如下:

    此外,IOException 有如下衍生类:

    ReaderWriter 及其衍生类是处理u nicode 文本。如我们看到的BufferedReaderInputStreamReader 或者 FileReader

    InputStreamOutputStream 及其衍生类是处理字节(byte)流。计算机中的数据都可以认为是字节形式,所以 InputStreamOutputStream 可用于处理更加广泛的数据。比如我们可以使用下面的组合来读取压缩文件中包含的数据(比如整数):

    箭头表示数据流动方向

    我们从压缩文件中读出字节流,然后解压缩,最终读出数据。




    写入

    写入(write)操作与读取操作相似。我们可以通过使用装饰,实现复杂的写入功能。这里是一个简单的写入文本的例子:

    import java.io.*;
    
    public class Test
    {
        public static void main(String[] args)
        {
            try {
                String content = "Thank you for your fish.";
    
                // new 一个文件对象
                File file = new File("new.txt");
    
                // 如果该文件不存在则创建它
                if (!file.exists()) {
                    file.createNewFile();
                }
    
                FileWriter fw = new FileWriter(file.getAbsoluteFile());
                BufferedWriter bw = new BufferedWriter(fw);
                bw.write(content);
                bw.close();
    
            }
            catch(IOException e) {
                System.out.println("IO Problem");
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:IO 基础

          本文链接:https://www.haomeiwen.com/subject/reywqftx.html