——JAVASE-IO流(下)

本文详细介绍了字符流的概念、常用方法及应用场景,并对比了字符流与字节流的操作规律,通过具体实例展示了如何使用字符流进行文本处理。

一、字符流
1、概念
字符流是可以直接读写字符的IO流,字符流读取字符, 就要先读取到字节数据, 然后转为字符. 如果要写出字符, 需要把字符转为字节再写出.
2、常用方法
(1) Reader
int read() 读取单个字符。
int read(char[] cbuf) 将字符读入数组。
int read(char[] cbuf, int off, int len) 将字符读入数组的某一部分。
close() ;关闭资源
(2) Writer
void write(char[] cbuf) 写入字符数组。
void write(char[] cbuf, int off, int len) 写入字符数组的某一部分。
void write(int c) 写入单个字符。
void write(String str) 写入字符串。
void write(String str, int off, int len) 写入字符串的某一部分。
close() 关闭此流,但要先刷新它。
abstract void flush() 刷新该流的缓冲。
3、字符流常用基类
(1) Reader
FileReader:字符读取流
BufferedReader:缓冲字符读取流
LineNumberReader:带行号的缓冲字符读取流
InputStreamReader:字节流通向字符流的桥梁
(2) Writer
FileWriter:字符写入流
BufferedWriter:缓冲字符写入流
OutputStreamWriter:字符流通向字节流的桥梁
4、什么情况下使用字符流
字符流也可以拷贝文本文件, 但不推荐使用. 因为读取时会把字节转为字符, 写出时还要把字符转回字节.
程序需要读取一段文本, 或者需要写出一段文本的时候可以使用字符流
5、字符流是否可以拷贝非纯文本的文件
不可以拷贝非纯文本的文件
因为在读的时候会将字节转换为字符,在转换过程中,可能找不到对应的字符,就会用?代替,写出的时候会将字符转换成字节写出去如果是?,直接写出,这样写出之后的文件就乱了,看不了了
6、自定义字符数组的拷贝

//创建字符输入流,关联aaa.txt
FileReader fr = new FileReader("aaa.txt");
 //创建字符输出流,关联bbb.txt          
FileWriter fw = new FileWriter("bbb.txt");
int len;
char[] arr = new char[1024*8];    //创建字符数组
while((len = fr.read(arr)) != -1)//将数据读到字符数组中
 {                 
    fw.write(arr, 0, len);    //从字符数组将数据写到文件上
}

fr.close();      //关闭资源
fw.close();  

7、flush方法与close方法的区别
flush是用来刷新缓冲区的,刷完之后还可以写出
close方法是用来关闭流的,在关闭之前会刷新一次缓冲区,刷完之后关闭,不可以再写出
8、带缓冲的字符流
BufferedReader的read()方法读取字符时会一次读取若干字符到缓冲区, 然后逐个返回给程序, 降低读取文件的次数, 提高效率
BufferedWriter的write()方法写出字符时会先写到缓冲区, 缓冲区写满时才会写到文件, 降低写文件的次数, 提高效率
BufferedReader的readLine()方法可以读取一行字符(不包含换行符号)
BufferedWriter的newLine()可以输出一个跨平台的换行符号”\r\n”

BufferedReader br = new BufferedReader(new FileReader("aaa.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("bbb.txt"));
String line;
while((line = br.readLine()) != null) {
    bw.write(line);
    //bw.write("\r\n");                 //只支持windows系统
    bw.newLine();                       //跨平台的
}
br.close();
bw.close();  

9、LineNumberReader
LineNumberReader是BufferedReader的子类, 具有相同的功能, 并且可以统计行号
调用getLineNumber()方法可以获取当前行号
调用setLineNumber()方法可以设置当前行号

LineNumberReader lnr = new LineNumberReader(new FileReader("aaa.txt"));
String line;
lnr.setLineNumber(100);               //设置行号
while((line = lnr.readLine()) != null) 
{ 
System.out.println(lnr.getLineNumber() + ":" + line);//获取行号
}
lnr.close(); 

10、使用指定的码表读写字符
FileReader是使用默认码表读取文件, 如果需要使用指定码表读取, 那么可以使用InputStreamReader(字节流,编码表)
FileWriter是使用默认码表写出文件, 如果需要使用指定码表写出, 那么可以使用OutputStreamWriter(字节流,编码表)

 //高效的用指定的编码表读
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("UTF-8.txt"), "UTF-8"));
BufferedWriter bw =     //高效的用指定的编码表写
        new BufferedWriter(new OutputStreamWriter(new FileOutputStream("GBK.txt"), "GBK"));
int ch;
while((ch = br.read()) != -1) {
    bw.write(ch);
}
br.close();
bw.close();

二、字符流和字节流的操作规律
遇到IO问题怎么考虑?
通过三个明确来完成:
(1) 明确操作的源和目的
源(输入流 ): InputStream和Reader
目的(输出流): OutputStream和Writer
(2) 操作的数据是否是纯文本
是:使用字符流
否:使用字节流
(3) 当体系明确后,再明确要使用哪个具体的对象,这是通过设备来进行区分的。
源设备:内存,硬盘,键盘
目的设备:内存,硬盘,控制台

需求:将键盘录入的数据保存到一个文件中
分析源:
1、源:InputStream和Reader
2、是纯文本吗?是,选择Reader体系
3、设备:键盘,对应的对象是System.in
因为选择的是Reader体系,但是System.in对应的是字节流。为了操作键盘的文本数据方便,将System.in转成字符流,按照字符串操作最方便,使用Read-
er体系中的转换流InputStreamReader。需要提高效率吗?要的话再选择缓冲技术BufferedReader。
分析目的:
1、目的:OutputStream和Writer
2、是纯文本吗?是,选择Writer体系
3、设备:硬盘,操作文件,使用FileWriter
   需提高效率吗?要,选择缓冲技术BufferedWriter
代码:
import java.io.*;
class  TransStreamDemo
{
    public static void main(String[] args) throws IOException
    {   //获取键盘录入对象。
        InputStream in = System.in;
    //将字节流对象转成字符流对象,使用转换流。InputStreamReader
        InputStreamReader isr = new InputStreamReader(in);
 //为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader
      BufferedReader bufr = new BufferedReader(isr);
  /*键盘的最常见写法。
  BufferedReader bufr = 
        new BufferedReader(new InputStreamReader(System.in));*/
  BufferedWriter bufw = 
        new BufferedWriter(new FileWriter("1.txt"));
    String line = null;
    while((line=bufr.readLine())!=null)
        {
            if("over".equals(line))
                break;
            bufw.write(line.toUpperCase());
            bufw.newLine();
            bufw.flush();
        }
     bufr.close();
     }
}

三、装饰设计模式
当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。那么自定义的该类称为装饰类。
装饰类通常会通过构造方法接收被装饰的对象。
并基于被装饰的对象的功能,提供更强的功能。

class Person//被装饰的对象
{
    public void chifan()
    {
        System.out.println("吃饭");
    }
}
class SuperPerson//装饰类 
{
    private Person p ;
    SuperPerson(Person p)
    {
        this.p = p;
    }
    public void superChifan()
    {
        System.out.println("开胃酒");
        p.chifan();
        System.out.println("甜点");
        System.out.println("来一根");
    }
}
class  PersonDemo
{
    public static void main(String[] args) 
    {
        Person p = new Person();
        //p.chifan();
        SuperPerson sp = new SuperPerson(p);
        sp.superChifan();
        }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值