热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

黑马程序员——Java基础——IO流、字符流、字节流、缓冲区技术、装饰设计模式、LineNumberReader等

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流!------一、IO流概述1、概述IO流:(InputOutputStrea

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ------

 一、IO流概述

      1、概述

         IO:(Input Output Stream)

      2、特点

        1) IO流用来处理设备间的数据传输。

        2Java对数据的操作是通过流的方式。

        3Java用于操作流的对象都在IO包中。

        4)流按操作数据分为两种:字节流和字符流。

        5)流按流向分为:输入流和输出流

      字符流用来处理文本数据,而除了文本数据以外,都是字节流的处理对象。

    3IO流的常用基类

         IO流中有n多个子类,形成一个体系。体系中一共有四个基类。对于数据的操作,只有两种:读和写。

           1) 字节流的抽象基类

                  inputStream(读)  OutputStream(写)

           2) 字符流的抽象基类

                  Reader     Writer

    注:  由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。

           如:InputStream的子类FileInputStream

           如:Reader的子类FileReader

           如何使用IO体系呢?先找IO包,java.IO中的四个基类。

  二、字符流

     1、概述

         public abstract class Writer   extends Object   implements Appendable, Closeable, Flushable

             写入字符流的抽象类。

       字符流用于处理文本数据。使用的是编码表,我们的机器中默认使用的是GBK。美国默认的是UTF-8.

       子类必须实现的方法仅有 write(char[], int, int)flush() 和 close()。但是,多数子类将重写此处定义的一些方法,以提供更高的效率和/或其他功能。 看到构造函数被protected修饰,我们就明白,这是供子类使用的。方法全是抽象的,是需要被子类实现的。既然IO流是用于操作数据的。那么数据的最常见体现形式是:文件。

    一个专门用于操作文件的Writer子类对象,FileWriter。后缀名是父类名,前缀名是该流对象的功能。

    2、字符流操作

        1)写入字符流

        a  创建一个FileWriter对象,它没有空参数的构造函数,所以该对象一被初始化,就必须要明确被操作的文件。如果该目录下如果已有同名文件,则同名文件将被覆盖。

        b调用write(String s)方法,将字符串写入到流中。

        c调用flush()方法,刷新该流的缓冲,将数据刷新到目的地中。

        d调用close()方法,关闭流资源。但是关闭前会刷新一次内部的缓冲数据,并将数据刷新到目的地中。

close()flush()区别:

        flush()刷新后,流可以继续使用;

       而close()刷新后,将会关闭流,不可再写入字符流。

       注意:记得关闭资源,因为是java在调用系统的底层资源完成读写操作的。

             文件的数据的续写是通过构造函数FileWriter(Strings,boolean append),在创建对象时,传递一个true参数,代表不覆盖已有的文件。并在已有文件的末尾处进行数据续写。

             由于在创建对象时,需要指定创建文件位置,如果指定的位置不存在,就会发生IOException异常,所以,需要对IO异常进行处理。

          

 

 

 

说明:Flush()close()的区别:

 A   Close()关闭流资源,但是,关闭之前会刷新一次内部的缓冲中的数据,将数据刷到目的地中。

 B   Flush()刷新后,流可以继续使用。Close()刷新后,会将流关闭。

      我们知道,我们直接在图形界面窗口中,也能新建文件,并写入数据,其实调用的就是windows内部的文件操作。 其实,java本身是不能在文件中写数据的,因为它是基于平台的,平台不同,内部的操作方式也不同,所以java是依赖调用系统内部的文件操作来写数据。所以是在使用系统的资源。所以,有一个动作一定要做,就是close();close()的内部就是先调用一次flush(),然后再到底层关闭下资源。

 C 两者都抛出IOException

   比如:write(),有可能写数据写到没内存了。Close(),有可能关闭不了。   

 2)文本文件读取方式一

        A 创建一个文件读取流对象,和指定名称的文件相关联。该文件若不存在,将会发生异常FileNotFoundException

       FileReader(String fileName)     在给定从中读取数据的文件名的情况下创建一个新 FileReader

       B调用读取流对象的read()方法。read():一次读一个字符,且会继续往下读。

              第一种方式:读取单个字符。第二种方式:通过字符数组进行读取。

       C调用close方法关闭流资源。

 

3)文本文件读取方式二

 public int read(char[] cbuf)  throws IOException

将字符读入数组。在某个输入可用、发生 I/O 错误或者已到达流的末尾前,此方法一直阻塞。

返回:读取的字符数,如果已到达流的末尾,则返回 -1 

注意:返回的是字符个数。通过字符数组进行读取

 

 

如果文件超大呢?缓冲区buf定义多少比较合适呢?通常我们定义的是1024的整数倍。

char[]buf=new char[1024];//2kb的数据。

两种读取方式,比较下来,这种方式比较好。

 

4IO异常处理方式

       凡是能和设备上发生数据操作时,都可能发生IO异常。

     A FileWriter fw=new FileWriter(demo.txt);有可能发生读取文件不存在,空指针异常

     B  write()发生内存溢出等异常

     C  close()发生关闭资源失败等异常

         因为这三条语句经常在一起,所以用一个try处理就可以,对应多个catch处理

   一个完整的IO异常处理方式

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 FileWriter fw=null;try{  fw=new FileWriter(“demo.txt”);  fw.write(“abcdefg”);}catch(IOException e){  System.out.println(e.toString())}finally{      try     {      if(fw!=null)//写到try上面,也没有问题。        fw.close();     }      Catc h(IOException e)      {         System.out.println(e.toString());      }}

 如果我们开了5个文件流,记得,要一个一个关,不能用fw=null||fw1!=null来判断,要一步一步来。

  5)练习

  读取一个.java文件,并打印到控制台上。

 

 

练习二

C盘一个文本文件复制到D

 

 

 

 

三、IO流缓冲区技术      

   1概述

      缓冲区的优点是提高了流的读写效率,在流的基础上对流的功能进行了增强。很多软件都加载自己的缓冲区,如下载软件。

     public  class  BufferedWriter  extends Writer

     将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

     查阅api,发现该类的构造函数没有空参数的,这是为什么?

     我们知道,缓冲区的出现,是为了提高流的读写效率。所以,缓冲区产生之前,一定先有流。

  2、缓冲技术原理:封装数组,将数据存入,再一次性取出。

  3、写入流缓冲区BufferedWriter的步骤:

        1)创建一个字符写入流对象。

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

        2)为了提高字符写入流效率。加入缓冲技术。只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。

        如:BufferedWriter bufw =new BufferedWriter(fw);

         3)调用write方法写入数据到指定文件

         如:bufw.write("java come");

         记住,只要用到缓冲区,就要记得刷新。(关闭流同样会刷新,但为了排除意外事故,保证数据存在,建议写入一次就刷新一次)

         4)缓冲区是为提高效率的而创建的,真正调用资源的是FileWriter对象所以其实关闭缓冲区,就是在关闭缓冲区中的流对象。

        如:bufw.close();

        BufferedWriter缓冲区中提供了一个跨平台的换行符:newLine();可以在不同操作系统上调用,用作数据换行。   newLine()函数里面就是,如果是windows系统,就是write(\r\n)如果是lunix系统,就是write(\n).

   

 

   4、读取流缓冲区BufferedReader的步骤

         public class BufferedReaderextends Reader

   从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

  构造函数:   BufferedReader(Reader in)  创建一个使用默认大小输入缓冲区的缓冲字符输入流。

        1)创建一个读取流对象和文件相关联

        如:FileReader fr=newFileReader("buf.txt");

        2)为了提高效率。加入缓冲技术。将字符读取流对象作为参数传递给缓冲区对象的构造函数。

        如:BufferedReader bufr=new BufferedReader(fr);

        3)该缓冲区提供了一个一次读一行的方法readLine().方便于对文本数据的获取。当返回null时,表示读到文件末尾。返回的字符串不包含行终止符。     

        如:String str=bufr.readLine();

readLine方法的原理:无论是读一行,或者读取多个字符,其实最终都是在硬盘上一个一个读取,最终使用的都是read()一次读一个。

        4)关闭流资源   

 

 

要注意的是读取循环结束的条件。

练习

通过缓冲区复制一个.java文件

 

 

 

 

 

 

四、IO流——自定义缓冲区技术

1、实现原理

  基于的是read方法。定义一个存储单位,然后,把一行数据存进去,满行后,再返回来。

明白了BufferedReader类中特有方法readLine的原理后,可以自定义一个类中包含一个功能和readLine一致的方法。来模拟一个BufferedReader

2、实现方法:

1)自定义一个缓冲区类

2)成员变量为FileReader对象。

3)自定义一个newline方法,用StringBuilder类实现。

3、练习

 

 

 

 

 

五、IO流——装饰设计模式

   1、概述

    通过简单模拟,我们发现readLine方法底层运用的还是read方法,它的出现是增强了read方法的功能。

BufferedReader就是对FileReader的增强

思想:

   增强功能,是通过被增强的对象传递给增强类。

这种设计模式叫做装饰设计模式。

  2、定义

装饰设计模式:当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有对象的功能,并提供加强功能。那么,自定义的该类就称为装饰类。

  装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。

3、装饰和继承的区别

   1)装饰模式比继承要灵活,避免了继承体系臃肿

   2)降低了类与类之间的关系。

   3)将继承结构转变为组合结构。

注意

装饰类因为增强已有对象,具备的功能和已有对象是相同的,只不过提供了更强的功能,所以,装饰类和被装饰类通常都属于一个体系中的。

4、自定义装饰类

     我们定义的MyBufferedReader就是一个装饰类,现在定义的只能对一个方法进行包装。

那么我们要装饰一组类,怎么办?传进他们的父类Reader就可以了。

class  MyBufferedReader  extends Reader{ private  Reader r;   MyBufferedReader(Reader r)   {        this.r=r;   }}

六、IO流——LineNumberReader

   1、概述

     BufferedReader的直接子类LineNumberReader

   public class LineNumberReaderextends BufferedReader

   跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int) 和 getLineNumber(),它们可分别用于设置和获取当前行号。

   默认情况下,行编号从 开始。该行号随数据读取在每个行结束符处递增,并且可以通过调用 setLineNumber(int) 更改行号。但要注意的是,setLineNumber(int) 不会实际更改流中的当前位置;它只更改将由 getLineNumber() 返回的值。

   可认为行在遇到以下符号之一时结束:换行符('\n')、回车符('\r')、回车后紧跟换行符。

也有BufferedReader有的方法readLine()read等等。

它也是一个包装类,或者叫做装饰类。

 2、特有方法

      setLineNumber(); 设置初始行号

      getLineNumber(); 获取行号

 3、练习

   

 

练习二:自定义带行号的缓冲区类

 

 


------- Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ------- 
推荐阅读
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • LeetCode笔记:剑指Offer 41. 数据流中的中位数(Java、堆、优先队列、知识点)
    本文介绍了LeetCode剑指Offer 41题的解题思路和代码实现,主要涉及了Java中的优先队列和堆排序的知识点。优先队列是Queue接口的实现,可以对其中的元素进行排序,采用小顶堆的方式进行排序。本文还介绍了Java中queue的offer、poll、add、remove、element、peek等方法的区别和用法。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
author-avatar
纸鸢漫天飞舞
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有