在说字符流之前,我们先简单说一下IO流的概念
IO流:处理设备之间的数据传输
Input Output
按照方向分:输入流,输出流
按照操作的数据分:字节流,字符流
字节流:可以操作任何类型的数据实现输入和输出
文本,音频,视频,图片
字符流:只能针对文本实现输入和输出
在字节流的基础上融入了编码,方便文本的输入和输出
字节流:两个父类
字节输入流的父类: InputStream
字节输出流的父类:OutputStream
字符流:两个父类
字符输入流的父类:Reader
字符输出流的父类:Writer
对于IO流的应用,我们的选其实比较自由,但是需要注意的就是字符流一般操作的是文本文件,而字节流可以操作任何文件,包括音频视频等。
FileWriter fw = new FileWriter("temp.txt");
//创建输出流对象,输出文件不存在会自动生成
fw.write("abcd");
//输出字符到文件
fw.flush();
//把内部缓冲中的数据刷新到文件中
fw.close();
//关闭流,同时会刷新流中的数据到文件中
FileReader fr = new FileReader("temp.txt");
//文件必须事先存在,不存在会抛异常
char[] arr = new char[1024];
int num;
while((num=fr.read(arr))!=-1)
{
System.out.print(new String(arr,0,num));
}
//读文件内容
对于异常的捕获,我们一般这样写,不过多解释。
import java.io.*;
class Demo2
{
public static void main(String[] args)
{
FileWriter fw = null;
try
{
fw = new FileWriter("k:\\temp.txt");//因为路径错误所以导致FileWriter对象创建失败FileNotFoundException
fw.write("abcde");
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
if(fw!=null)
fw.close();//null.close()---NullPointerException
}
catch (IOException e)
{
throw new RuntimeException("写入流关闭失败");
}
}
}
}
为了提高IO流的效率,有字符流缓冲区对象,字符流缓冲区本身并不能读取或者输出字符,只是为了提高效率
InputStream,OutputStream
Reader,Writer
FileWriter:
write("");
flush()
close()
FileReader:
int read() -1
int read(char[] arr) -1
字符流的缓冲区:缓冲区是为了提高读或写的效率
只具备提高效率的功能,不具备读或写的功能
使用缓冲流必须结合着读流或写流
BufferedReader:只具备提高效率的功能,不具备读的功能
BufferedWriter: 只具备提高效率的功能,不具备写的功能----newLine()
class Demo8
{
public static void main(String[] args)throws IOException
{
//使用缓冲写入流实现文件的写入
//1.因为BufferedWriter不具备写入的功能,所以需要先创建字符写入流对象和文件相关联
FileWriter fw =new FileWriter("tt.txt");
//2.为了提高写入的效率,使用缓冲写入流
//把需要被提高效率的字符输出流对象作为参数传递给BufferedWriter的构造方法
BufferedWriter bw = new BufferedWriter(fw);
//3.使用BufferedWriter对象实现写入数据
for(int i=1;i<=3;i++)
{
bw.write("abc"+i);
bw.newLine();//写入换行---跨平台的
bw.flush();
}
//关闭流
bw.close();//关闭缓冲流其实就是关闭字符输出流
}
}
下面延伸一下说明Buffered对象是怎样实现的,我们实现其read(),readLine()和close()方法
/*
模拟BufferedReader,自定义一个类MyBufferedReader
1:需要一个真正具备读功能的流对象,所以MyBufferedReader需要定义一个Reader类型的成员
2:通过提供一个缓冲区来提高效率的,所以需要定义一个数组
3:操作数组需要下标,所以需要定义一个下标
4:统计字符的个数,所以需要定义一个变量
readLine() read() close()
*/
import java.io.*;
class MyBufferedReader
{
private Reader r;//具备读功能的成员
private char[] arr = new char[1024];//提高效率的缓冲区
private int index;
private int count;//统计缓冲区中的字符个数
public MyBufferedReader(Reader r)
{
this.r = r;
}
//一次读一个字符的功能
public int myRead()throws IOException
{
//先判断缓冲区中是否有字符
if(count==0)
{
//从文件中读一批数据到缓冲区
count = r.read(arr);
index = 0;//下标置为0,从头开始取
}
if(count<0)
return -1;
int num = arr[index];//从缓冲区中去一个字符
count--;//数量减1
index++;
return num;
}
//一次读一行的功能
//反复调用myRead()方法,不够一行的时候存储,够一行的时候返回
public String myReadLine()throws IOException
{
StringBuilder sb = new StringBuilder();//实现存储字符 \r\n
int num;
while((num = myRead())!=-1)
{
if(num=='\r')
continue;
else if(num=='\n')
return sb.toString();
else
sb.append((char)num);
}
return null;
}
public void myClose()throws IOException
{
r.close();
}
}
class Demo11
{
public static void main(String[] args) throws IOException
{
FileReader fr = new FileReader("tt.txt");
MyBufferedReader mbr = new MyBufferedReader(fr);
String line = null;
while((line = mbr.myReadLine())!=null)
{
System.out.println(line);
}
mbr.myClose();
}
}