说明
输入输出(I/O)是指程序与外部设备或其他计算机进行交互的操作。几乎所有的程序都具有输入与输出操作,如从键盘上读取数据,从本地或网络上的文件读取数据或写入数据等。通过输入和输出操作可以从外界接收信息,或者是把信息传递给外界。Java把这些输入与输出操作用流来实现,通过统一的接口来表示,从而使程序设计更为简单。
Java的IO流是实现输入输出的基础,它可以方便地实现数据的输入/输出操作,java中把不同的输入源(键盘、网络、文件等)输出源(硬盘、网络、文件等)抽象表述为“流”,通过”流“的方式允许Java程序使用相同的方式来访问不同的输入/输出源,其中输入和输出的数据称为数据流(Data Stream)。
I/O流类概述
为了方便流的处理,Java语言提供了java.io包,在该包中的每一个类都代表了一种特定的输入或输出流。为了使用这些流类,编程时需要引入这个包。 Java提供了两种类型的输入输出流:一种是面向字节的流,数据的处理以字节为基本单位;另一种是面向字符的流,用于字符数据的处理。字节流(Byte Stream)每次读写8位二进制数,也称为二进制字节流或位流。字符流一次读写16位二进制数,并将其做一个字符而不是二进制位来处理。需要注意的是,为满足字符的国际化表示,Java语言的字符编码采用的是16位的Unicode码,而普通文本文件中采用的是8位ASCⅡ码。
java.io中类的层次结构如图所示。
流的分类
按照不同的分类方式,可以将流分为不同的类型。
输入流和输出流
按照流的流向来分可以分为输入流和输出流。
- 输入流:只能从中读取数据,而不能向其写出数据
输出流:只能向其写出数据,而不能从中读取数据
Java的输入流主要由InputStream和Reader作为基类;Java的输出流主要由OutputStream和Writer作为基类。
字节流和字符类流
字节流以字节为传输单位,用来读写8位的数据,除了能够处理纯文本文件之外,还能用来处理二进制文件的数据。 InputStream类和OutputStream类是所有字节流的父类。
字符流是针对字符数据的特点进行过优化的,因而提供一些面向字符的有用特性,字符流的源或目标通常是文本文件。 Reader和Writer是java.io包中所有字符流的父类。由于它们都是抽象类,所以应使用它们的子类来创建实体对象,利用对象来处理相关的读写操作。
节点流和处理流
按流的角色分,可以分为节点流和处理流。
Reader和Writer的子类又可以分为两大类:一类用来从数据源读入数据或往目的地写出数据(称为节点流),另一类对数据执行某种处理(称为处理流)。
可以从/向一个特定的I/O设备(如磁盘/网络)读/写数据的流,称为节点流,常常也被称为低级流;
处理流则用于对一个已存在的流进行连接或封装,通过封装后的流来实现数据读/写功能,处理流也称为高级流。
字节流的核心类
InputStream类
面向字节的输入流都是InputStream类的子类,其类层次结构如图所示。
下表列出了 InputStream 的主要子类及说明:
InputStream 流类中包含一套所有输入都需要的方法,可以完成最基本的从输入流读入数据的功能。下表列出了其中常用的方法及说明。
InputStream是抽象类,本身不能创建实例,但他有一个很常用的用于读取文件的子类:FileInputStream。同时该核心类的核心方法为int read(byte[] b, int off, int len)。
- b - 存储字节数据的数组
- off - 偏移量。读进来的数据从数组的哪个位置开始存放
- len - 读取的最大字节数
- 返回值为读取的字节数。
FileInputStream
该流用于从文件读取数据,它的对象可以用关键字new来创建。
有多种构造方法可用来创建对象。
可以使用字符串类型的文件名来创建一个输入流对象来读取文件:
InputStream f = new FileInputStream("C:/java/hello");
下面先看一个简单的使用例子:
我们首先在e:/src目录下新建一个from.txt和to.txt文件。其次在from.txt文件中写入数据“abcd”;我们的目的是从from.txt中读取这些数据。
public class Test {
public static void main(String[] args){
//声明输入流引用
FileInputStream fis = null;
try{
//生成代表输入流的对象
fis = new FileInputStream("E:/src/from.txt");
//生成一个字节数组
byte[] buffer = new byte[100];
//调用输入流对象的read()方法,读取数据
int temp = fis.read(buffer, 0, buffer.length);
String s = new String(buffer);
//调用String对象的trim方法将会去掉这个字符串的首尾空格和空字符
s = s.trim();
System.out.println(s);
//遍历输出数组元素
for(int i = 0;i < buffer.length;i++){
System.out.println(buffer[i]);
}
}catch(Exception e){
System.out.println(e);
}
}
}
输出结果:
abcd
97
98
99
100
0
.
.
.
从结果上可以看出我们已经成功的读取到from.txt文件中数据。
OutputStream类
面向字节的输出流都是OutputStream类的子类,其类层次结构如图所示。
下表列出了OutputStream的主要子类及说明。
OutputStream流类中包含一套所有输出都需要的方法,可以完成最基本的向输出流写入数据的功能。下表列出了其中常用的方法及说明。
OutputStream是抽象类,本身不能创建实例,但他有一个很常用的用于读取文件的子类:FileOutputStream。同时该核心类的核心方法为int write(byte[] b, int off, int len)。
- b - 存储数据的数组
- off - 数据中的开始偏移
len -写入的字节数
FileOutputStream
该类用来创建一个文件并向文件中写数据。
如果该流在打开文件进行输出前,目标文件不存在,那么该流会创建该文件。
有两个构造方法可以用来创建FileOutputStream 对象。
使用字符串类型的文件名来创建一个输出流对象:
OutputStream f = new FileOutputStream("C:/java/hello")
我们将上面程序中读到的数据放入to.txt文件中:
public class Exercise1 {
public static void main(String[] args){
//声明输入流引用
FileInputStream fis = null;
//声明输出流引用
FileOutputStream fos = null;
try{
//生成代表输入流的对象
fis = new FileInputStream("E:/src/from.txt");
//生成代表输出流的对象
fos = new FileOutputStream("E:/src/to.txt");
//生成一个字节数组
byte[] buffer = new byte[100];
//调用输入流对象的read()方法,读取数据,temp为返回的字节数
int temp = fis.read(buffer, 0, buffer.length);
//String s = new String(buffer);
//调用String对象的trim方法将会去掉这个字符串的首尾空格和空字符
//s = s.trim();
//System.out.println(s);
for(int i = 0;i < buffer.length;i++){
System.out.println(buffer[i]);
}
fos.write(buffer, 0, temp);
}catch(Exception e){
System.out.println(e);
}
}
}
打开to.txt文件即可发现已经成功写入“abcd”字符串。