1.基本概念
I/O(Input/Output):输入输出
数据源(Data Source):数据的来源,可以是文件,数据库等等
数据宿(Data Sink):数据传输到的终端(destination)
Java中把不同的数据源与程序间的数据传输都抽象表述为“流”(Stream),java.io包中定义了多种I/O流类型实现数据I/O功能。
I/O流分类:
输入流(Input Stream)和输出流(Output Stream)
节点流(Node Stream)和处理流(Processing Stream)
字符流(Character Stream)和字节流(Byte Stream)
2.分类解析
输入流(Input Stream)和输出流(Output Stream)
按照 数 据 流 动 的 方 向 , Java 流 可 分 为 输 入 流(Input Stream)和输出流(Output Stream)
输入流只能从中读取数据,而不能向其写出数据;输出流则只能向其写出数据,而不能从中读取数据;
特例:java.io.RandomAccessFile类。 (它既可以写,也可以读)
节点流(Node Stream)和处理流(Processing Stream)
根据数据流所关联的是数据源还是其他数据流,可分 为 节 点 流 ( Node Stream)和 处 理 流(Processing Stream)
节点流直接连接到数据源处理流是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现增强的数据读/写功能,处理流并不直接连到数据源。

字符流(Character Stream)和字节流(Byte Stream)
按传输数据的“ 颗粒大小” 划分,可分为字符流(Character Stream)和字节流(Byte Stream)
字节流以字节为单位进行数据传输,每次传送一个或多个字节;字符流以字符为单位进行数据传输,每次传送一个或多个字符。
Java命名惯例:凡是以InputStream或OutputStream结尾的类型均为字节流,凡是以Reader或Writer结尾的均为字符流。
3.InputStream 和 OutputStream
抽象类java.io.InputStream 是所有字节输入流类型的父类,该类中定义了以字节为单位读取数据的基本方法,并在其子类中进行了分化和实现。
三个基本的read方法:
int read():读取一个字节(8位),将这个字节的高24位补零,转换成了一个int(32位),并输出
int read(byte[] buffer):从当前的数据源中成批的读取数据并保存到buffer数组中,如果实际读取的字节数小于buffer数组的大小,则返回实际读取的字节数
int read(byte[] buffer, int offset, int length):与上面的方法类似,如果实际读取的字节数小于length的大小,则返回实际读取的字节数
其它方法:
void close()
int available():数据源后面还有多少个可以读入的字节数
skip(long n):跳过n个字节
boolean markSupported():是否支持做标记(在InputStream的子类中进行了分化)
void mark(int readlimit):在不超过readlimit范围内可以重新跳到标记处
void reset():跳转到原来标记的地方
InputStream层次

java.io.OutputStream与java.io.InputStream对应,是所有字节输出流类型的抽象父类。
三个基本的write方法:
void write(int c):将参数int对应的整型的高24位丢弃,剩下的8位作为一个字节输出到当前关联的数据宿
void write(byte[] buffer):将buffer的数组中的内容输出到当前关联的数据宿
void write(byte[] buffer, int offset, int length):将buffer的数组中从下标offset长度为length的内容输出到当前关联的数据宿
其它方法:
void close()
void flush():清空输出缓冲区
层次:

4.Reader 和 Writer
抽象类java.io.Reader 是所有字符输入流类型的父类,其中声明了用于读取字符流的有关方法。
三个基本的read方法:
int read():从当前关联的输入流中读取一个字符,并将这个字符的高16位补零后转换成int类型并返回
int read(char[] cbuf):从当前关联的输入流中读取cbuf.length个字符并填充到数组cbuf中,如果没有length个返回实际的大小
int read(char[] cbuf, int offset, int length)
其它方法:
void close()
boolean ready():判断当前的字符流是否就绪
skip(long n)
boolean markSupported()
void mark(int readAheadLimit)
void reset()

java.io.Writer与java.io.Reader类对应,是所有字符输出流类型的共同父类。
五个基本的write方法:
void write(int c):将int的低16位转换成一个char并输出到当前关联的输出流中
void write(char[] cbuf)
void write(char[] cbuf, int offset, int length)
void write(String string):将字符串string写出到当前关联的输出流中
void write(String string, int offset, int length)
其它方法:
void close()
void flush()

5.常用的IO流类型
①FileInputStream/FileOutputStream
FileInputStream 用 于 读 取 本 地 文 件 中 字 节 数 据 ,FileOutputStream用于将字节数据写出到文件。
例14-1 使用字节流实现文件复制
package v512.chap14; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class CopyFile{ public static void main(String[] args) { try { FileInputStream fis = new FileInputStream ("D:\\test.txt"); FileOutputStream fos = new FileOutputStream ("D:\\testcopy.txt"); int read = fis.read(); while ( read != -1 ) { fos.write(read); read = fis.read(); } fis.close(); fos.close(); } catch (IOException e) { e.printStackTrace(); } } }
结果就是D盘下面多了一个文件,testcopy.txt,而且内容和 test.txt 一样
②FileReader/FileWriter
FileReader用于以字符为单位读取文本文件,FileWriter类用于将字符数据写出到文本文件中。
例14-2 使用字符流实现文件复制
import java.io.*; public class Test { public static void main(String[] args) { try { FileReader input = new FileReader("a.txt"); FileWriter output = new FileWriter("temp.txt"); int read = input.read(); while ( read != -1 ) { output.write(read); read = input.read(); } input.close(); output.close(); } catch (IOException e) { System.out.println(e); } } }
在JavaVM中字符是用UniCode编码保存的(每个字符占2个字节),保存在系统磁盘中的文本文件是使用的是当前操作系统默认的字符编码
(中文操作系统:GBK)在读写文件时是先对文本文件按照本地的字符编码进行编码,然后再转换成Unicode编码格式
③BufferedReader/BufferedWriter
BufferedReader用于缓冲读取字符,BufferedWriter则提供字符的缓冲写出功能。
例14-3 使用字符处理流实现文件复制