java作为一种面向对象语言,程序的一切都动作行为都是通过对象完成。所谓IO流,就是把数据的传输行为封装成了对象,对于数据的传输过程,也就变成了对IO流对象的操作过程:
IO流的分类
1.按数据的传输方向分类(也就根据数据的传输方向分,数据的源头与数据目的地):
输入流:硬盘、网络、或输入设备等地方的数据向内存输送(输入流的基类 InputStream Reader)。
输出流:与输入流相反,数据从内存向硬盘、网络、或输入设备等地方输送(输出流的基类 OutputStream Writer)。
2.按流的数据处理的数据类型:
字节流:处理字节数据(基类 InputStream OutputStream)
字符流:处理字符数据(基类Reader Writer)
对于上面所述的四个基类的关系:
1
类分类 | 输入流 | 输出流 |
---|---|---|
字节流 | InputStream | OutputStream |
字符流 | Reader | Writer |
2、字符流的底层是字节流,也就是说字符流是通过字节流实现
IO流的应用:
上面的介绍的四个基类流(InputStream OutputStream Reader Writer)都是抽象类,起到是对IO类共性抽取,并描述的作用。 他们具有了他们所对应子类的IO流对象的主要方法,通过学习基类方法,了解IO流子类对象的一般操作方法。
InputStream 基本方法:
read() 读取一个字节以整数形式返回,如果返回-1已到输入流的末尾。
close() 关闭流,因为读写文件是对地产资源的操作,所以关闭,以便流释放内存资源。
OutputStream 基本方法:
write(int b )向输出流写入一个字节数据。
flush() 将输出流中缓冲的数据全部写出。
close() 关闭流释放内存资源。
Reader 与Writer用法与InputStream、OutputStream类相同,不同之处在于前者读取的是字节,后者使读取的是字符,下面我们用Reader 与Writer类的子类写一个复制文件的程序。
代码块
public class Test11 {
public static void main(String[] args) {
long start = System.currentTimeMillis();
myCopy();
long end = System.currentTimeMillis();
//运行时间
System.out.println(end-start+"毫秒");
}
public static void myCopy()
{
Reader read =null;
Writer writer = null;
try {
// 生成读写流对象,指定要操作的文件。
read = new FileReader("d:\\1.txt");
writer = new FileWriter("d:\\copy.txt");
char[] chs =new char[100];
int len = 0;
//复制文件
while((len=read.read(chs))!=-1)
{
writer.write(chs,0,len);
writer.flush();
}
} catch ( IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally
{
if(read!=null)
try {
read.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(writer!=null)
try {
writer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
这样我们就完成了对一个文件的复制。
在程序中,我打印出了复制文件过程中函数的运行时间。
节点流:
在上面的程序中用到了俩个IO类,FileReader、FileWriter,分别是Reader、Writer的子类,第一个完成对文件的读,另一个读文件写。在IO流体系中为了提过读写流的读写效率,提供了节点流,目的在于方便读写、提高效率。接下来我们会介绍一些节点流。
IO缓冲流
BufferedWriter
BufferedReader
缓冲流要结合流才可以使用,在流的基础上对流的功能进行了增强。这是一种装饰者模式,即把已有的IO流对象通过一些修饰,增强了对象的读写功能以及效率。
BufferedWriter
在创建该类的对象时要求一个Writer类的子类对象,而BufferedWriter就是该对象的读写起到缓冲的作用,BufferedWriter包含了Writer相同的方法,但是效率高于Writer的方法,自身也具有一些特殊的方法。
newLine() 写进写入一个行分隔符。
BufferedReader与BufferedWriter有类似的特点,修饰的是Readerde 的子类对象,自身也具有一些特殊的方法。
readLine() 一次读写一行字符。
前面我们已经写了一个复制文件的程序,同时打印出复制文件所用的时间,现在我们通过对读写流加上缓冲流,再次复制文件,通过打印出复制所用时间看是否能够有效提高运行效率。
代码块:
public static void main(String[] args) {
long start = System.currentTimeMillis();
myCopy();
long end = System.currentTimeMillis();
//运行时间
System.out.println(end-start+"毫秒");
}
public static void myCopy()
{
BufferedReader read =null;
BufferedWriter writer = null;
try {
// 对IO流加上缓冲流
read = new BufferedReader(new FileReader("d:\\1.txt"));
writer =new BufferedWriter( new FileWriter("d:\\copy.txt"));
String line=null;
//复制文件
while((line=read.readLine())!=null)
{
writer.write(line);
writer.newLine();
writer.flush();
}
} catch ( IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally
{
if(read!=null)
try {
read.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(writer!=null)
try {
writer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
在上一个程序的基础上加上了缓冲流,对比前后俩个程序代码的运行时间,我们会发现后面的程序的运行时间少于前面,通过这两个程序的比较,我们能够直观的看到加了缓冲留的文件的读写效率会更高,同时缓冲流提供的方法读写起来更加方便。这就是IO流体系中节点流的特点,方便操作,提高效率。
转换流
InputStreamReader
OutputStreamWriter
我们已经知道了IO流可以分为字节流与字符流,而字符流的底层是字节流。字节流到字符流的转换是通过两个转换流实(InputStreamReader、OutputStreamWriter),它们是字符流与字节流之间的桥梁,方便了字符流与字节流之间的操作。具体的的实现原理是字节流把读写到的字节到指定到码表找去相应的字符,返回找到的字符。
那么为什么要把 字节流对象转换为字符流对象呢,同样是为了提高效率,方便操作,一次读写一个字符的效率要比一次读写一个字节的效率高,同时对字符的操作的更加直观。
InputStreamReader:
把读的字节IO流对象转换为相对应的字符读对象,
OutputStreamWriter:
把写的字节IO流对象转换为相对应的字符写对象
然我们用一个简单的程序说明字节与字符间的转换,同样是用复制文件,上面的第一个程序我们已经用字节流对象复制了文件,现在我们把字节流转换为字符流,用字符流对文件进行复制。
代码:
public static void main(String[] args) {
InputStreamReader read = null;
OutputStreamWriter writer =null;
try {
//把字节流转换为字符流
read = new InputStreamReader(new FileInputStream("d:\\1.txt"));
writer = new OutputStreamWriter(new FileOutputStream("d:\\copy.txt"));
// 复制文件操作
char[] ch = new char[100];
int len = 0;
while((len = read.read(ch))!=-1)
{
writer.write(ch,0,len);
}
} catch ( Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally
{
//关闭流资源
if(read!=null)
try {
read.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(writer!=null)
try {
writer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
就这样我们用转换流完成了一次文件的复制。
总结
为了能够对数据传输进行操作,引入了IO流, IO流主要是有四个抽象类(InputStream ,OutputStream、Reader ,Writer)作为基类,该类是对IO流功能起到描述作用,我们通过生成相对应子类对象对文件进行操作,为了提高读写效率,产生了节点流,是对读写流起到修饰的作用,我们只对部分节点流做了介绍(BufferedWriter、BufferedReader、InputStreamReader,OutputStreamWriter)。