Java进阶03 IO基础

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明。谢谢!

 

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

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

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

 

IO示例

 下面是我用于演示的文件file.txt

Hello World!
Hello Nerd!

 

我们先来研究一个文件读取的例子:

import java.io.*;

public class Test
{
    public static void main(String[] args)
    {
        try {            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");
        }
    }
}

这段程序中包含一个try...catch...finally的异常处理器。可参考Java进阶02 异常处理

 

装饰器与功能组合

程序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()修饰,从而实现缓存读取。

 

下图显示了br的工作方式,数据自下而上流动:

 

(文本流可参考Linux文本流TCP协议与流通信)

上述的装饰过程与Linux中的文本流思想很相似。在Linux中,我们使用类似函数的方式来处理和传递文本流。在Java中,我们使用了装饰器。但它们的目的都类似,就是实现功能的模块化和自由组合。

 

更多的组合

事实上,Java提供了丰富的装饰器。FileReader中合并了读取和转换两个步骤,并采用了常用的默认设置,比如编码采取unicode。我们可以使用FileInputStream + InputStreamReader的组合来替代FileReader,从而分离读取字节和转换两个步骤,并对两个过程有更好的控制。

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

箭头表示数据流动方向

 

流的读写来自于四个基类: InputStream, OutputStream, Reader和Writer。InputStream和Reader是处理读取操作,OutputStream和Writer是处理写入操作。它们都位于java.io包中。继承关系如下:

 

java.io

 

此外,IOException有如下衍生类:

IOException

 

Reader和Writer及其衍生类是处理unicode文本。如我们看到的Buffered Reader, InputStreamReader或者FileReader。

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

箭头表示数据流动方向

 

 

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

 

写入

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

import java.io.*;

public class Test
{
    public static void main(String[] args)
    {
        try {
            String content = "Thank you for your fish.";

            File file = new File("new.txt");

            // create the file if doesn't exists
            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");
        }
    }
}

上面创建了file对象,用于处理文件路径。

 

总结

这里只是对Java IO的基本介绍。Java的IO相对比较复杂。Java程序员需要花一些时间来熟悉java.io中的类及其功能。

 

欢迎继续阅读“Java快速教程”系列文章

 

时间: 2024-10-12 06:00:54

Java进阶03 IO基础的相关文章

Java进阶学习(三) IO基础

计算机最重要的功能是处理数据.一个有用的计算机语言需要拥有良好的IO功能,以便让未处理的数据流入程序,让已处理的数据流出. 与其他语言相比,Java的IO功能显得复杂.在其他语言中,许多IO功能(比如读取文件),是被封装好的,可以用一两行程序实现.在Java中,程序员往往需要多个层次的装饰(decoration),才能实现文件读取. 相对的复杂性带来的好处是IO的灵活性.在Java中,程序员可以控制IO的整个流程,从而设计出最好的IO方式.我们将在下文看到更多. IO示例 下面是我用于演示的文件

Java进阶学习(一) String类

之前的Java基础系列中讨论了Java最核心的概念,特别是面向对象的基础.在Java进阶中,我将对Java基础进行补充,并转向应用层面. 大部分编程语言都能够处理字符串(String).字符串是有序的字符集合,比如"Hello World!".在Java中,字符串被存储为String类对象.调用字符串对象的方法,可以实现字符串相关的操作. String类包含在java.lang包中.这个包会在Java启动的时候自动import,所以可以当做一个内置类(built-in class).我

Java Mybatis框架入门基础教程_基础知识

一.Mybatis介绍 MyBatis是一款一流的支持自定义SQL.存储过程和高级映射的持久化框架.MyBatis几乎消除了所有的JDBC代码,也基本不需要手工去 设置参数和获取检索结果.MyBatis能够使用简单的XML格式或者注解进行来配置,能够映射基本数据元素.Map接口和POJOs(普通java对象)到数据库中的记录. 二.MyBatis工作流程 (1)加载配置并初始化 触发条件:加载配置文件 配置来源于两个地方,一处是配置文件,一处是Java代码的注解,将SQL的配置信息加载成为一个个

Java进阶教程之异常处理_java

程序很难做到完美,不免有各种各样的异常.比如程序本身有bug,比如程序打印时打印机没有纸了,比如内存不足.为了解决这些异常,我们需要知道异常发生的原因.对于一些常见的异常,我们还可以提供一定的应对预案.C语言中的异常处理是简单的通过函数返回值来实现的,但返回值代表的含义往往是由惯例决定的.程序员需要查询大量的资料,才可能找到一个模糊的原因.面向对象语言,比如C++, Java, Python往往有更加复杂的异常处理机制.这里讨论Java中的异常处理机制. Java异常处理 异常处理 Java的异

Java进阶01 String类

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢!   之前的Java基础系列中讨论了Java最核心的概念,特别是面向对象的基础.在Java进阶中,我将对Java基础进行补充,并转向应用层面.   大部分编程语言都能够处理字符串(String).字符串是有序的字符集合,比如"Hello World!".在Java中,字符串被存储为String类对象.调用字符串对象的方法,可以实现字符串相关的操作. String类包含在j

Java网络03 Servlet沙拉

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.   Servlet开胃酒中介绍了Servlet的基本流程和设置方式.这里,我们将看一些Servlet实例.这些实例都是HTTP通信(参考HTTP协议)中的常见问题.我们通过操作request和response,来实现HTTP协议的功能.   生成页面 Servlet的目的是动态生成页面.比如下面的例子: package foo; import javax.servlet.*; impo

JAVA进阶之旅(一)——增强for循环,基本数据类型的自动拆箱与装箱,享元设计模式,枚举的概述,枚举的应用,枚举的构造方法,枚举的抽象方法

JAVA进阶之旅(一)--增强for循环,基本数据类型的自动拆箱与装箱,享元设计模式,枚举的概述,枚举的应用,枚举的构造方法,枚举的抽象方法 学完我们的java之旅,其实收获还是很多的,但是依然还有很多的知识点需要我们的突破,所以写下这个java进阶之旅的系列,这个系列不会说的那么的基础,主要是对一些高级点的功能进行剖析,所以,一起来看看吧! 一.增强for循环 for循环在我们的开发中是非常非常的多的,但是有多少人会用增强for循环?其实还是有很多人会用哈,但是还是有很多人一知半解,我们来看一

Java 进阶面试问题列表

翻译自Java developer interview questions: The hard part 面向对象编程的基本理念与核心设计思想 解释下多态性(polymorphism),封装性(encapsulation),内聚(cohesion)以及耦合(coupling). 继承(Inheritance)与聚合(Aggregation)的区别在哪里. 你是如何理解干净的代码(Clean Code)与技术负载(Technical Debt)的. 描述下常用的重构技巧. 阐述下SOLID原则.

JAVA进阶之旅(二)——认识Class类,反射的概念,Constructor,Field,Method,反射Main方法,数组的反射和实践

JAVA进阶之旅(二)--认识Class类,反射的概念,Constructor,Field,Method,反射Main方法,数组的反射和实践 我们继续聊JAVA,这次比较有意思,那就是反射了 一.认识Class类 想要反射,你就必须要了解一个类--Class,我们知道,java程序中的各个java类都属于同一事物,我们通常用Classliability描述对吧,反射这个概念从JDK1.2就出来了,历史算是比较悠久了,这个Class可不是关键字哦,这个是一个类,他代表的是一类事物: 我们归根结底就