Java:IO流之字符流缓冲区详解-阿里云开发者社区

开发者社区> 吞吞吐吐的> 正文

Java:IO流之字符流缓冲区详解

简介:
+关注继续查看
字符流缓冲区:
1、缓冲区的出现提高了对数据的读写效率;
2、对应类:BufferedWriter、BufferedReader;
3、缓冲区要结合流才可以使用;
4、在流的基础上对流的功能进行了增强。
 
注意:缓冲区的出现是为了提高流的操作效率而出现的,所以在创建缓冲区之前必须现有流对象。
 
java.io 
类 BufferedReader:读入缓冲区
 
构造方法摘要 
BufferedReader(Reader in) 创建一个使用默认大小输入缓冲区的缓冲字符输入流。 
BufferedReader(Reader in, int sz) 创建一个使用指定大小输入缓冲区的缓冲字符输入流。 
主要方法摘要 
 void close() 关闭该流并释放与之关联的所有资源。  
 int read() 作为一个整数(其范围从0到65535(0x00-0xffff)读入的字符,如果已到达流末尾,则返回 -1,读取单个字符。 
 int read(char[] cbuf, int off, int len) 将字符读入数组的某一部分。 
 String readLine() //包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null ,读取一个文本行。 

 //例子1:

复制代码
import java.io.*;
class BufferedReaderDemo
{
    public static void main(String[] args) throws IOException
    {
        //创建一个字符读入流对象,和目的地文件相关联.
        FileReader fr = new FileReader("F:\\myfile\\buf.txt");
        
        //为了提高字符读入流效率,加入了缓冲技术,只需要将被提高效率的流对象作为参数
        //传递给缓冲区的构造函数即可。此时,缓冲区和流相关联.
        BufferedReader buf = new BufferedReader(fr);
        int num = 0;
        String line = null;
        
        /*
        while((line = buf.readLine())!=null) //此过程中,读入缓冲区一行一行的读取数据,效率高
        {
            System.out.println(line);
        }
        */
        
        while((num = buf.read())!=-1)
        {
         System.out.print((char)num);        
        }

       //其实关闭缓冲区,就是关闭缓冲区中的流对象
        buf.close();
    }
}
复制代码

 

readLine方法的原理:尽管是读取一行获取多个字符,其实最终都是在硬盘上一个一个地读取字符。所以最终使用的还是read方法一次读一个的方法。
明白了BufferedReader类中特有方法readLine的原理后,
可以自定义一个类中包含一个功能和readLine一致的方法,
来模拟一个BufferedReader
(该代码中的思想体现了装饰设计模式)
//例子2:
复制代码
import java.io.*;
class MyBufferedReader extends Reader
{
    private Reader r;
    MyBufferedReader(Reader r)
    {
        this.r = r;
    } 
    //可以一次读一行的方法
    public String MyreadLine() throws IOException
    {
     //定义一个临时容器。原BufferedReader封装的是字符数组。
     //为了演示方便,定义一个StringBuilder容器,因为最终还是要将数据变为字符串
      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)   //出现读取一行数据到了缓冲区,但是该字符串后面没有'\n',可是仍要把它读取出来。
            return sb.toString();
      return null;      
    }
    //覆盖Reader中的抽象方法
    public int read(char[] cbuf, int off, int len) throws IOException
    {
        return r.(cbuf,off,len);
    }
    public void close()throws IOException
    {
        r.close();
    }

    public void Myclose()throws IOException
    {
        r.close();
    }
}
//测试类
class MyBufferedReaderTest { public static void main(String[] args) { FileReader fr = null; MyBufferedReader mybuf = null; String line = null; try { mybuf = new MyBufferedReader(new FileReader("F:\\myfile\\buf.txt")); while((line = mybuf.MyreadLine())!=null) { System.out.println(line); } } catch(IOException e) { throw new RuntimeException("读入流异常"); } finally { try { mybuf.Myclose(); } catch(IOException e) { throw new RuntimeException("关闭流异常"); } } } }
复制代码

自定义一个统计行号的类:MyLineNumberReader,可以设置复制得到的文件内容的行号

//例子3:
复制代码
import java.io.*;
/*
class MyLineNumberReader extends MyBufferedReader
{
    private int linenumber;
    MyLineNumberReader(Reader r)
    {
        super(r);
    }
    public void setLineNumber(int linenumber)
    {
        this.linenumber = linenumber;
    }
    public int getLineNumber()
    {
        return linenumber;
    }
    public String MyreadLine() throws IOException
    {   
        linenumber++;//每读一行,行数就自加一次
        return super.MyreadLine();
    }
}
*/
class MyLineNumberReader
{
    private Reader r;
    private int linenumber;
    MyLineNumberReader(Reader r)
    {
        this.r = r;
    }
    public void setLineNumber(int linenumber)
    {
        this.linenumber = linenumber;
    }
    public int getLineNumber()
    {
        return linenumber;
    }
    public String MyreadLine() throws IOException
    {   
        linenumber++;//每读一行,行数就自加一次
        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();
    }
}
class MyLineNumberReaderDemo
{
    public static void main(String[] args)
    {
        FileReader fr = null;
        MyLineNumberReader myl = null;
        String str = null;
        try
        {
          fr  = new FileReader("MyBufferedReaderTest.java");
          myl = new MyLineNumberReader(fr);
          //myl.setLineNumber(100);  //设置第一行从101行开始
          while((str = myl.MyreadLine())!=null)
           {
             System.out.println(myl.getLineNumber()+":"+str);
           }              
        }
        catch(IOException e)
        {
            System.out.println("流读入异常!");
        }
        finally
        {
            try
            {
                myl.Myclose();
            }
            catch(IOException e)
            {
                System.out.println("流关闭异常!");
            }
        
        }        
    }
}
复制代码

 

java.io 
类 BufferedWriter:写入缓冲区

构造方法摘要 

BufferedWriter(Writer out) 创建一个使用默认大小输出缓冲区的缓冲字符输出流。 

BufferedWriter(Writer out, int sz) 创建一个使用给定大小输出缓冲区的新缓冲字符输出流。 

方法摘要 

void close() 关闭此流,但要先刷新它。 

void flush() 刷新该流的缓冲。 

void newLine() 写入一个行分隔符。具有跨平台性,相当于windows系统的"\r\n"和linux系统的"\n";

void write(char[] cbuf, int off, int len) 写入字符数组的某一部分。 

void write(int c) 写入单个字符。 

void write(String s, int off, int len) 写入字符串的某一部分。 

//例子4:
复制代码
import java.io.*;
class BufferedWriterDemo
{
    public static void main(String[] args) throws IOException
    {
        //创建一个字符写入流对象,和目的地文件相关联.
        FileWriter fw = new FileWriter("F:\\myfile\\buf.txt");
        
        //为了提高字符写入流效率,加入了缓冲技术,只需要将被提高效率的流对象作为参数
        //传递给缓冲区的构造函数即可。此时,缓冲区和流相关联.
        BufferedWriter buf = new BufferedWriter(fw);
        
        buf.write("abcdefg");
        for(int i=0;i<3;i++)
        {
        buf.newLine();//换行
        buf.write("changjiang"+i);
        //记住,只要用到缓冲区,必须要刷新
        buf.flush();        
        }
        //其实关闭缓冲区,就是关闭缓冲区中的流对象
        buf.close();
    }
}
复制代码

 

使用字符流缓冲的一个综合实例如下:
要求:通过一个缓冲区复制一个.java文件
注意:readLine()方法返回的时候只返回回车符之前的数据内容,并不返回回车符。
//例子5: 没有异常处理时:
复制代码
import java.io.*;
class BufferedCopyTest
{
    public static void main(String[] args)throws IOException
    {
        //创建一个读入流对象,与要被复制的文件相关联
        FileReader fr = new FileReader("BufferedReaderDemo.java");
        //创建一个写入流对象,与目的文件相关联
        FileWriter fw = new FileWriter("BufferedReaderDemo_Copy.txt");
        
        //创建一个读入缓冲区,与流对象相关联
        BufferedReader bufr = new BufferedReader(fr);
        //创建一个写入缓冲区,与流对象相关联
        BufferedWriter bufw = new BufferedWriter(fw);        
        
        //读取数据存入缓冲区中
        String line;
        while((line = bufr.readLine())!=null)
        {
            bufw.write(line);
            bufw.newLine();
            bufw.flush();
        }
        bufw.close();
        bufr.close();
    }
}
复制代码
//例子6: 有异常的处理时:
复制代码
import java.io.*;
class BufferedCopyTest2
{
    public static void main(String[] args)
    {
        BufferedReader bufr = null;
        BufferedWriter bufw = null;
        try
        {
         bufr = new BufferedReader(new FileReader("BufferedReaderDemo.java"));
         bufw = new BufferedWriter(new FileWriter("BufferedReader_Copy.txt"));                
         String line;
          while((line = bufr.readLine())!=null)
          {
            System.out.println(line);  
            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("关闭流异常");  
          }
        }
    }
}
复制代码

 

 

 

程序猿神奇的手,每时每刻,这双手都在改变着世界的交互方式!
本文转自当天真遇到现实博客园博客,原文链接:http://www.cnblogs.com/XYQ-208910/p/4917994.html,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,大概有三种登录方式:
2962 0
阿里云服务器ECS远程登录用户名密码查询方法
阿里云服务器ECS远程连接登录输入用户名和密码,阿里云没有默认密码,如果购买时没设置需要先重置实例密码,Windows用户名是administrator,Linux账号是root,阿小云来详细说下阿里云服务器远程登录连接用户名和密码查询方法
11612 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
10882 0
使用OpenApi弹性释放和设置云服务器ECS释放
云服务器ECS的一个重要特性就是按需创建资源。您可以在业务高峰期按需弹性的自定义规则进行资源创建,在完成业务计算的时候释放资源。本篇将提供几个Tips帮助您更加容易和自动化的完成云服务器的释放和弹性设置。
12071 0
阿里云服务器安全组设置内网互通的方法
虽然0.0.0.0/0使用非常方便,但是发现很多同学使用它来做内网互通,这是有安全风险的,实例有可能会在经典网络被内网IP访问到。下面介绍一下四种安全的内网互联设置方法。 购买前请先:领取阿里云幸运券,有很多优惠,可到下文中领取。
11818 0
腾讯云服务器 设置ngxin + fastdfs +tomcat 开机自启动
在tomcat中新建一个可以启动的 .sh 脚本文件 /usr/local/tomcat7/bin/ export JAVA_HOME=/usr/local/java/jdk7 export PATH=$JAVA_HOME/bin/:$PATH export CLASSPATH=.
4659 0
如何设置阿里云服务器安全组?阿里云安全组规则详细解说
阿里云安全组设置详细图文教程(收藏起来) 阿里云服务器安全组设置规则分享,阿里云服务器安全组如何放行端口设置教程。阿里云会要求客户设置安全组,如果不设置,阿里云会指定默认的安全组。那么,这个安全组是什么呢?顾名思义,就是为了服务器安全设置的。安全组其实就是一个虚拟的防火墙,可以让用户从端口、IP的维度来筛选对应服务器的访问者,从而形成一个云上的安全域。
7490 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
7365 0
阿里云服务器ECS登录用户名是什么?系统不同默认账号也不同
阿里云服务器Windows系统默认用户名administrator,Linux镜像服务器用户名root
4502 0
4852
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载