IO 基础

计算机最重要的功能是处理数据。一个有用的计算机语言需要拥有良好的 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");
        }
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,045评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,114评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,120评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,902评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,828评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,132评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,590评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,258评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,408评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,335评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,385评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,068评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,660评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,747评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,967评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,406评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,970评论 2 341

推荐阅读更多精彩内容

  • 一、基础知识:1、JVM、JRE和JDK的区别:JVM(Java Virtual Machine):java虚拟机...
    杀小贼阅读 2,360评论 0 4
  • 一、File 类 java.io.File 类:文件和目录路径名的抽象表示形式。通过File对象可以访问文件的属性...
    七弦桐语阅读 392评论 0 1
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,537评论 18 399
  • 以前没觉得
    你叫我啥阅读 168评论 0 0
  • ️#青蛙打卡#B1刘文华9月1日江西26/100 【百日目标】 1.23:00/7:00 2.【阅读6/12+运动...
    Twinkle_L阅读 173评论 0 0