java复习:IO流基础字符流

1、 IO概述

(1)概述
IO流:即InputOutput的缩写。是用来处理设备间(内存、硬盘)的数据传输。

(2)IO流的常用基类:
a.字节流的抽象基流:InputStream和OutputStream
b.字符流的抽象基流:Reader和Writer

注:此四个类派生出来的子类名称都是以父类名作为子类名的后缀,以前缀为其功能;如InputStream子类FileInputStream;Reader子类FileReader

(2)特点:
1)IO流用来处理设备间的数据传输。
2)Java对数据的操作是通过流的方式。
3)Java用于操作流的对象都在IO包中。
4)流按操作数据分为两种:字节流和字符流。
5)流按流向分为:输入流和输出流。

注意:流只能操作数据,而不能操作文件。

2、字符流 FileWriter和FileReader

字符流中的对象融合了编码表。使用的是默认的编码,即当前系统的编码。字符流只用于处理文字数据,而字节流可以处理媒体数据。既然IO流是用于操作数据的,那么数据的最常见体现形式是文件。

  • 2.1 输入流
    查看API,找到一个专门用于操作文件的Writer子类对象:FileWriter。 后缀是父类名。前缀名是流对象的功能。该流对象一被初始化,就必须有被操作的文件存在。
    这里写图片描述
    这里写图片描述
    这里写图片描述

  • (1) IO输入流的基本用法和IO的异常处理

import java.util.*;
import java.io.*;
class FileWriterDemo1
{
    public static void main(String[] args)
    {
        FileWriter fw=null;//在外部建立引用,在内部建立对象。如果都在内部建立在finally中就找不到fw
        try
        {
            fw=new FileWriter("K://demo.txt");
            fw.write("安徽");
        }
        catch (IOException e)//如果创建的为“K://demo.txt”则系统找不到指定的路径就会报告异常NUllPointEXception
        {
            System.out.println(e.toString());
        }
        finally
        {
            try
            {
                if(fw!=null)//如果fw为空的情况下,不应该执行关闭的操作,不应调用close()。如果有5个流对象,得分别关闭5次。
                    fw.close();
            }
            catch (IOException e)
            {
                System.out.println(e.toString());
            }
        }
    }
}

这里写图片描述

  • (2) 文件的续写
//需求:文件的续写,假如文件中已经有内容“原来文件内容”;添加新的信息文件续写
import java.util.*;
import java.io.*;
class FileWriterDemo2
{
    public static void main(String[] args)
    {
        FileWriter fw=null;//在外部建立引用,在内部建立对象。如果都在内部建立在finally中就找不到fw
        try
        {
            fw=new FileWriter("demo.txt",true);
            fw.write("续写\r\n信息");
        }
        catch (IOException e)//如果创建的为“K://demo.txt”则系统找不到指定的路径就会报告异常NUllPointEXception
        {
            System.out.println(e.toString());
        }
        finally
        {
            try
            {
                if(fw!=null)//如果fw为空的情况下,不应该执行关闭的操作,不应调用close()。如果有5个流对象,得分别关闭5次。
                    fw.close();
            }
            catch (IOException e)
            {
                System.out.println(e.toString());
            }
        }
    }
}

这里写图片描述

  • 2.2 输出流
    查看API,找到一个专门用于操作文件的Writer子类对象:FileWriter。 后缀是父类名。前缀名是流对象的功能。该流对象一被初始化,就必须有被操作的文件存在。
    这里写图片描述
    这里写图片描述
    这里写图片描述
    举例说明:
//需求:读取文件的内容,并打印到控制台上
import java.util.*;
import java.io.*;
class FileReaderDemo3 
{
    public static void main(String[] args) 
    {
        FileReader fr=null;
        try
        {
            fr=new FileReader("demo.txt");
/************************第一种***************************/
            while (true)
            {
                int ch=fr.read();
                if (ch==-1)     
                break;
                System.out.print((char)ch);
            }
/************************第二种***************************/
            while (true)
            {
                int ch=0;
                while ((ch=fr.read())!=-1)
                {
                    System.out.print((char)ch);
                }
                break;
            }
/************************第三种***************************/
            char[] buf=new char[3];
            int num=0;
            while ((num=fr.read(buf))!=-1)
            {
                System.out.print(new String(buf,0,num));
            }
        }
/**********************************************************/
        catch (IOException e)
        {
            System.out.println(e.toString());
        }

        finally 
        {
            try
            {
                fr.close();
            }
            catch (IOException e)
            {
                System.out.println(e.toString());
            }
        }   
    }
}

这里写图片描述

  • 2.3 拷贝文件
//需求:demo.txt中的文本信息拷贝到copydemo.txt中去
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
class  CopyDemo4
{
    public static void main(String[] args) 
    {
        private static final int BUFFER_SIZE=1024;
        FileWriter fw=null;
        FileReader fr=null;
        try
        {
            fw=new FileWriter("Copydemo.txt");
            fr=new FileReader("demo.txt");
            char[] buf=new char[BUFFER_SIZE];
            int num=0;
            while ((num=fr.read(buf))!=-1)
            {
                fw.write(buf,0,num);
            }

        }
        catch (IOException e)
        {
            System.out.println(e.toString());
        }
        finally 
        {
            try
            {
                if (fr!=null)
                fr.close();
            }
            catch (IOException e)
            {
                System.out.println(e.toString());
            }
            try
            {
                if (fw!=null)
                fw.close();
            }
            catch (IOException e)
            {
                System.out.println(e.toString());
            }

        }   
    }
}

3、字符流缓冲区

  • 3.1 BufferedReader和BufferedWriter简介

这里写图片描述

(1)假如缓冲区是为了提高效率,但是真正的操作还是FileWriter(),关闭缓冲区就是关闭缓冲区的流对象。
(2)newLine()写入一个行分隔符,具有跨平台性。

这里写图片描述
public String readLine() throws IOException
读取一个文本行。通过下列字符之一即可认为某行已终止:换行 (‘\n’)、回车 (‘\r’) 或回车后直接跟着换行。
返回:包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null

  • 3.2 缓冲区文件复制
import java.io.*;
class  BufCopyDemo1
{
    public static void main(String[] args) 
    {
        BufferedWriter bufw=null;
        BufferedReader bufr=null;
        try
        {
            bufw=new BufferedWriter(new FileWriter("copydemo.txt"));
            bufr=new BufferedReader(new FileReader("demo.txt"));
            String line=null;
            while ((line=bufr.readLine())!=null)
            {
                bufw.write(line);
                bufw.newLine();
                bufw.flush();
            }
        }
        catch (IOException e)
        {
            throw new RuntimeException("读写失败");
        }
        finally
        {
            try
            {
                if (bufr!=null)
                bufr.close();
            }
            catch (IOException e)
            {
                throw new RuntimeException("读写关闭失败");
            }
            try
            {
                if (bufw!=null)
                bufw.close();
            }
            catch (IOException e)
            {
                throw new RuntimeException("读写关闭失败");
            }
        }
    }
}

这里写图片描述

  • 3.3 自定义的缓冲区文件内容的复制
/*
需求:既然明白了readLine()的原理,可以自定义一个类中包含一个功能和readLine()一致的方法来模拟BufferedReader()
*/
import java.io.*;
class BufCopDemo2 
{
    public static void main(String[] args)throws IOException
    {
        FileReader fr=new FileReader("demo.txt");//
        MyBufferedReader mybuf=new MyBufferedReader(fr);
        String line=null;
        while ((line=mybuf.myReadLine())!=null)
        {
            System.out.println(line);
        }
        mybuf.myClose();
    }
}
class MyBufferedReader
{
    private FileReader r;//为了流对象作用于整个类,需要定义成员变量
    MyBufferedReader(FileReader r)
    {
        this.r=r;
    }
    /*定义一个临时容器,原BufferedReader中定义的是字符数组,但是需要使用的指针概念.可以使用StringBuilder容器来存储,因为最终还是将数据变成字符串*/
    public String myReadLine() throws IOException
    {
        StringBuilder sb=new StringBuilder();
        int ch=0;
        while ((ch=r.read())!=-1)
        {
            if (ch=='\r')
            continue;
            if (ch=='\n')
            return sb.toString();
            else
            sb.append((char)ch);
        }
        if (sb.length()!=0)
            return sb.toString();
            return null;    
    }
    public void myClose() throws IOException
    {
        r.close();
    }
}
  • 3.4 LineNumberReader
    这里写图片描述
import java.io.*;
class  LineNumberReaderDemo
{
    public static void main(String[] args) throws IOException
    {
        FileReader fr=new FileReader("demo.txt");
        LineNumberReader lnr=new LineNumberReader(fr);
        String line=null;
        lnr.setLineNumber(100);
        while ((line=lnr.readLine())!=null)
        {
            System.out.println(lnr.getLineNumber()+">>"+line);
        }
        lnr.close();
    }
}

这里写图片描述

4、IO流的装饰设计模式

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

例如:
一个人具有基本的功能吃饭

class Person
{
    public static void eat()
    {
        System.out.println("吃饭");
    }
}

进行装饰,功能增强后:

class SuperPerson
{
    private Person p;
    SuperPerson(Person p)
    {
        this.p=p;
    }
    public static void supereat()
    {
        System.out.println(“开胃酒”);
        p.chifan();
        System.out.println("甜点");
    }
}
class Demo
{
    public static void main(String[] args)
    {
        Person p=new Person();
        SuperPerson sp=new SuperPerson(p);
        sp.superchifan();
    }
}
  • 4.2 继承和装饰的区别
首先有一个继承体系:Writer
|--TextWriter:用于操作文本
    |--BufferTextWriter:加入了缓冲技术的操作文本的对象,对操作的动作进行效率的提高。
|--MediaWriter:用于操作媒体
    |--BufferMediaWriter:加入了缓冲技术的操作媒体的对象,对操作的动作进行效率的提高。

以上方式并不理想,如果这个体系需要再进行功能扩展,又多了更多流对象。这样就会发现只为提高功能,导致继承体系越来越臃肿,不够灵活。

解决问题:
既然加入的都是同一种技术–缓冲。
将缓冲进行单独的封装,哪个对象需要缓冲就将哪个对象和缓冲关联。

class BufferedWriter extends Writer
{
     BufferedWriter(Writer w){}
}

装饰比继承更加的灵活。避免了继承体系臃肿,而且降低了类与类之间的关系。但是装饰类和被装饰类必须所属同一个接口和父类。装饰类因为增强已有对象。具备的功能和已有也是相同的,只不过提供了更强的功能。

举例说明:

/****************************************************************************
自定义一个读取缓冲区类,模拟一BufferedReader
分析:缓冲区无非就是封装了一个数组,并对外提供了更多的方法对数组进行访问,
其实这些方法最终操作都是数组的角标。
缓冲的原理:其实就是从源中获取一批数据到缓冲区中,再从缓冲区不断地取出一个
一个数据。在此次取完后,再从源中继续取一批数据进缓冲区,当源中的数据取完时,
用-1作为结束标记.
****************************************************************************/
import java.io.*;
class MyBufferedReader
{
    private Reader r;
    private char[] buf = new char[1024]; //定义一个数组作为缓冲区
    private int pos = 0; //定义一个指针用于操作这个数组中的元素,当操作到最后一个元素后,指针应该归零
    private int count = 0; //定义一个计数器用于记录缓冲区中的数据个数,当该数据减到0,就从源中继续获取数据到缓冲区中
    MyBufferedReader(Reader r)
    {
        this .r = r;
    }
    public int myRead() throws IOException//该方法从缓冲区中一次取一个字符
    {
        if (count == 0)//从源中获取一批数据到缓冲区中,需要先做判断,只有计数器为0时,才需要从源中获取数据
        {
            count = r.read(buf);    
            pos = 0;//每次获取数据到缓冲区后,角标归零
        }
        if (count < 0)
        return -1;
        char ch = buf[pos];
        pos++;
        count--;
        return ch;
    }
    public String myReadLine() throws IOException 
    {
        StringBuilder sb = new StringBuilder();
        int ch = 0;
        while ((ch = myRead()) != -1)
        {
            if (ch == '\r' )
            continue ;
            if (ch == '\n' )
            return sb.toString();
            sb.append(( char )ch);//将从缓冲区读到的字符,存储到缓存行数据的缓冲区中
        }
        if (sb.length() != 0)
        {
            return sb.toString();
        }
        return null ;
    }

    public void myClose() throws IOException
    {
        r.close();
    }
}
class MyBufferedReaderDemo
{
    public static void main(String[] args) throws IOException 
    {
        FileReader fr = new FileReader("buf.txt" );
        MyBufferedReader bufr = new MyBufferedReader(fr);
        String line = null ;
        while ((line = bufr.myReadLine()) != null)
        {
            System.out.println(line);
        }
        bufr.myClose();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值