十八、Java基础--------IO流体系以及字符流
在上一章节中详细介绍集合框架的相关知识,在接下来的几篇文章中将讲述Java中另一个及其重要的知识——IO流,本文主要是讲述IO流的一些基本概念以及字符流的相关应用。
IO流
介绍IO流之前先介绍一下什么是IO,IO是input、output的简称,所以所谓的IO流也就是输入输出流,明白了这一点对后面的学习有很大的促进作用。
流向分类
正如干电池有正极与负极一样,流也有方向的区别,我们常用的分类是按照流的流向进行分类, "流"向当前程序的流成为输入流也就是I的一端,"流"出当前程序的流成为输出流也就是O的一端,有了这个概念,我们便将IO流分为输入流和输出流。
流的基类
我们按照操作对象的不同将流分为两大门派,一派是操作字符数据的我们称之为字符流,操作字节的一派我们称之为字节流。体系结构如下:
字符流:Reader、Writer
字节流:InputStream、OutputStream
字节流:处理字节数据的流对象。我们熟知的设备上的数据无论是图片或者视频,文字,它们都以二进制存储的。二进制的最终都是以一个8位为数据单元进行体现,所以计算机中的最小数据单元就是字节。也就是说,字节流可以处理设备上的所有数据,所以字节流一样可以处理字符数据。
字符流:在中文平台的计算机上存储数据的编码是GBK,国标是unicode所以在互相转化时就会出现乱码,因此需要在获取中文字节数据的同时指定编码表才可以正确的解析数据。为了方便操作,所以将字节流和编码封装成对象,这个对象就是字符流。
需要特别指出的是,上述四个类别两个门派作为基本有一个特点,就是其子类都是以父类的名字结尾,这样就极大的方便我们去掌握,比如InputStream的子类FileInputStream;Writer的子类FileWriter.
字符流
抽象基类:
|--Reader:字符输入流
|--Writer:字符输出流
FileWriter
FileWriter是Writer的一个子类(而且是OutputStreamWriter的子类),用来写入字符文件的便捷子类
构造方法:
|--FileWriter(File file)
根据给定的 File 对象构造一个 FileWriter 对象。
|--FileWriter(File file, boolean append)
根据给定的 File对象构造一个 FileWriter 对象。
|--FileWriter(FileDescriptor fd)
构造与某个文件描述符相关联的 FileWriter 对象。
|--FileWriter(String fileName)
根据给定的文件名构造一个 FileWriter 对象。
|--FileWriter(String fileName, boolean append)
根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。
可以实现文件的追加写入,第二个参数表示是否追加写入,默认是false,就会重头开始写入,如果是true,就会追加写入
常用方法:
|--void write(String str):写入字符串。
|--abstract void flush():刷新该流的缓冲
|--abstract void close():关闭此流,但要先刷新它。
应用示范
1、FileWriter的使用范例
新建文件,并在文件中写入字符
import java.io.FileWriter;
import java.io.IOException;
public class Demo2 {
public static void main(String[] args) throws IOException {
//创建流对象,建立数据存放文件,指定目录和文件名
FileWriter f=new FileWriter("E:/aa.txt");
//调用FilterWriter的writer(String s)方法,向新建的文件中输出指定字符
f.write("我是 FileWriter创建的文件");
//刷新字符流中的数据,如果不刷新且不关闭流对象会出现空文件的现象
f.flush();
//关闭流对象,回收流资源,关闭流对象后流对象将无法使用,这与flush有着重大区别
f.close();
}
}
2、在已有的文件结尾添加字符,其实只需改动一处
FileWriter f=new FileWriter("E:/aa.txt",true);
其他部分内容相同
FileReader
FileReader是Reader的一个子类(是InputStreamReader的直接子类),用来读取字符文件的便捷类
构造方法:
|--FileReader(File file)
在给定从中读取数据的 File 的情况下创建一个新 FileReader。
|--FileReader(FileDescriptor fd)
在给定从中读取数据的 FileDescriptor 的情况下创建一个新 FileReader。
|--FileReader(String fileName)
在给定从中读取数据的文件名的情况下创建一个新 FileReader。
两种读取方法:
|--int read():读取单个字符。
|--int read(char[] cbuf):将字符读入数组。
应用示范
1、 read()
import java.io.FileReader;
import java.io.IOException;
public class Demo2 {
public static void main(String[] args) throws IOException {
//第一种方式read();
FileReader fr = new FileReader("E:/aa.txt");
//创建一个文件读取流对象,和指定名称的文件相关联。
//要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundException
int ch = 0;
while((ch = fr.read())!=-1){
System.out.print((char)ch);
}
fr.close();
}
}
第二中方式read(char[])
import java.io.FileReader;
import java.io.IOException;
public class Demo2 {
public static void main(String[] args) throws IOException {
//第二种方式read(char[]);
FileReader fr = new FileReader("E:/aa.txt");
int i = 0;
char[] ch2 = new char[1024];
while((i = fr.read(ch2))!=-1){
System.out.print(new String(ch2,0,i));
}
fr.close();
}
}
在上面介绍了基类Writer以及Reader的基本用法,不管是Writer还是Reader上面的用法有一个缺陷就是效率低,为了提高效率我们需要学习下面的内容——字符流缓冲区
字符流缓冲区
字符流缓冲区的出现就是为了提高对数据的读写效率,在流的基础上对功能进行增强,这里涉及一种设计模式——装饰设计模式,关于常见的设计模式在后面的文章中会有专题进行介绍这里不再详解。
常见缓冲区对应的类
BufferedWriter(? Extends Writer)
BufferedReader(? Extends Reader)
BufferedWriter
将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。该缓冲区中提供了一个跨平台的换行符:newLine();
本类方法(全部方法返回类型void):
|--close():关闭此流,但要先刷新它。
|--flush():刷新该流的缓冲。
|--newLine():写入一个行分隔符。 可跨平台使用
|--write(char[] cbuf, int off, int len):写入字符数组的某一部分。
|--write(int c):写入单个字符。
|--write(String s, int off, int len):写入字符串的某一部分。
使用示范
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class Demo2 {
public static void main(String[] args) throws IOException {
//创建一个字符写入流对象。
FileWriter fw = new FileWriter("E:/aa.txt");
//为了提高字符写入流效率。加入了缓冲技术。
//只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。
BufferedWriter bufw = new BufferedWriter(fw);
for(int x=1; x<5; x++){
bufw.write("第"+x+"次写入");
bufw.newLine();
bufw.flush();//只要用到缓冲区,就要记得刷新。
}
//其实关闭缓冲区,就是在关闭缓冲区中的流对象。
bufw.close();
}
}
BufferedReader
从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
该缓冲区提供了一个一次读一行的方法 readLine(),方便于对文本数据的获取。当返回null时,表示读到文件末尾。(注:readLine方法返回的时候只返回回车符之前的数据内容。并不返回回车符。)
常用方法:
|--void close():关闭该流并释放与之关联的所有资源。
|--int read():读取单个字符。
|--int read(char[] cbuf, int off, int len):将字符读入数组的某一部分。
|--String readLine():读取一个文本行。
使用范例
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Demo2 {
public static void main(String[] args) throws IOException {
//创建一个读取流对象和文件相关联。
FileReader fr = new FileReader("E:/aa.txt");
//为了提高效率。加入缓冲技术。将字符读取流对象作为参数传递给缓冲对象的构造函数。
BufferedReader bufr = new BufferedReader(fr);
String line = null;//定义一个用作临时存储数据的变量
while((line=bufr.readLine())!=null)//返回值不为null就一直循环
{
System.out.print(line);
}
bufr.close();
}
}