黑马程序员_十五 【字节流】【装饰模式】【LineNumberReader】

 

 

--------------------- android培训java培训、java学习型技术博客、期待与您交流! -------------------

 

 1  字节流 

字节流的读写操作

两个基类?

操作图片数据用什么流?

字节流的写入操作数组类型是什么?

字节流写入有什么特点?和字符流有什么区别?

字符流走的也是字节,但是会把字节存储起来,并进行查表。底层用还是字节流的缓冲区。直接使用字节流的话,因为单位是一个字节,所以一个一个读和写,不需要刷新。直接可以写入。但是关闭资源的close()方法一定要写上。

字符串如何转换成字节?字节如何转换成字符?

字节流读取的2个方式?

Available()是什么方法?怎么用?

返回对象中字节的个数。回车代表两个字符。直接被对象调用即可

import java.io.*;

class FileStream

{

      public static void main(String[] args) throws IOException

      {

           //writeFile();

           //readeFile_1();

           //readeFile_2();

           readeFile_3();

      }

      public static void readeFile_3()throws IOException

      {

           FileInputStream fis = newFileInputStream("fos.txt");

           //int num = fis.available();//可以得知文件的具体字节数

           byte[] buf = new byte [fis.available()];//定义一个刚刚好的缓冲区,不用再循环了。Available()返回对象中字节的个数。回车代表两个字符

           //这个方法的好处就可以读取刚刚好的数组。但是慎用,如果一个电影1g大小,用这个会把内存占满的。

           fis.read(buf);

           System.out.println(new String(buf);

           fis.close();

      }

      public static void readeFile_2()throws IOException

      {//另一种方式读取,通过建立字节数组

           FileInputStream fis = newFileInputStream("fos.txt");

           byte[] buf = new byte [1024];//数组

           int len = 0;

           while ((len=fis.read(buf))!=-1)//read(byte[] b) read的构造函数可以读取一个数组。

           {

                 System.out.println(newString(buf,0,len));//String(byte[] bytes, int offset, int length) 通过使用平台的默认字符集解码指定的 byte 子数组,构造一个新的 String。这个是构造函数,输出buf数组中从0开始的第len个元素,以字符串的形式输出

           }

           fis.close();

      }

      public static void readeFile_1()throws IOException//建立一个方法

      {

           FileInputStream fis = newFileInputStream("fos.txt");//建立一个字节流对象fis

           int ch = 0;

           while ((ch=fis.read())!=-1)//当读取不为-1时,继续执行下面的操作

           {

                 System.out.println((char)ch);//ch转换成char型输出

           }

           fis.close();

      }

      public static void writeFile()throws IOException

      {

           FileOutputStream fos = newFileOutputStream("fos.txt");       

           fos.write("abcde".getBytes());//getBytes()函数的作用是将字符流转换成字符写入到字节流中。

           //字节流不需要刷新,因为字节操作是最小的操作,直接可以进去写入操作字符流操作有点是以2个字节为一个字符的,所以需要刷新。

           fos.close();//虽然不用刷新,但仍然要执行这个操作,这样可以关闭流节省资源

      }

}

拷贝图片

思路:

1,用字节读取流对象和图片关联。

2,用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。

3,通过循环读写,完成数据的存储。

4,关闭资源。

import java.io.*;

class  CopyPic

{

      public static void main(String[] args)

      {//复制图片,用字符流是可以复制的,但是复制完的图片有可能打不开,因为字符流读完一段数据就会对照数码表,复制后文件有可能打不开

           

FileOutputStream fos = null;//建立2个字节流文件,

           FileInputStream fis = null;

           try

           {

                 fos = new FileOutputStream("c:\\2.jpg");//写入文件是2.jpg

                 fis = new FileInputStream("c:\\1.jpg");//读取的文件是1

                 byte[] buf =new byte[1024];//数组

                 int len = 0;

                 while ((len=fis.read(buf))!=-1)

                 {

                      fos.write(buf,0,len);//进行写入

                 }

           }

           catch (IOException e)

           {

                 throw new RuntimeException("复制失败");//如果上面的代码异常,就抛出复制失败

           }

           finally

           {

                 try

                 {

                      if(fis!=null)

                            fis.close();

                 }

                 catch (IOException e)

                 {

                      throw new RuntimeException("读取失败");

                 }

                 try

                 {

                      if(fos!=null)

                            fos.close();

                 }

                 catch (IOException e)

                 {

                      throw new RuntimeException("写入失败");

                 }

           }

      }

}

拷贝MP3

import java.io.*;

class  CopyMp3

{

      public static void main(String[] args) throws IOException

      {

           long start =System.currentTimeMillis();

           long end =System.currentTimeMillis();

           System.out.println("时间:"+(end-start)+"毫秒");//调用currentTimeMillis()函数计算使用多少时间

           copy_1();

      }

      public static void copy_1()throws IOException

      {

           BufferedInputStream bufis = new BufferedInputStream(newFileInputStream("c:\\1.mp3"));

           BufferedOutputStream bufos = new BufferedOutputStream(newFileOutputStream("c:\\2.mp3"));

           int len = 0;

           while ((len=bufis.read())!=-1)

           {

                 bufos.write(len);//进行写入

           }

           bufis.close();

           bufos.close();

      }

}

read(),write()的特点

自定义字节流缓冲区的代码?

为什么read()方法的返回值是int型?

如何读取键盘录入?

字符流转换字节流如何输入?

字节流转换字符流呢?

字节缓冲区读取的原理:

首先缓冲区定义了一个字节数组,然后从文件中抓了一堆数据,向数组里面存入,存满后,就读取,每读取一个字节,数组指针就减一。取完后数组指针指向0角标,再抓数据,从0角标开始继续存入。

自定义字节缓冲区会发现,read()方法第一个数值返回的就是-1。原因是读前八个字节如果都是1,那么返回成int型就都是-1.所以没法读取。如果想避免这种情况,就要转换int型的时候,前面3个八位补0,这样通过&255,就可以实现自定义字节流。

import java.io.*;

class MyBufferedInputStream//建立一个类,与BufferedInputStream功能一样。

{

      private InputStream in;

      private byte[] buf=new byte[1024*4];//建立数组

      private int pos = 0,count=0;

      MyBufferedInputStream(InputStream in)

      {

           this.in=in;

      }

      public int myRead()throws IOException

      {//通过in对象读取硬盘上的数据,并存储到buf

           if(count == 0)

           {

                 count = in.read(buf);//count值为读取buf后的int值,

                 if (count<0)//如果小于零,则返回-1,结束read函数

                      return -1;

                 pos=0;//每次count为零的时候。pos其实为1024*4-1,所以这条语句初始化pos

                 byte b = buf[pos];//buf[]中元素赋值给b

                 count--;//自减函数count

                 pos++;//自加函数pos

                 return b&255;//与上255,使每个8为字节前面的24个都为0,避免有-1字节的出现

           }

           else if (count >0)//如果大于零

           {

                 byte b = buf[pos];//就执行循环,把值赋给b

                 count--;

                 pos++;

                 return b&0xff;//统一将值与255。这个就是BufferedInputStream中的原理。read()方法返回的必须是int值,在做转换, 而write()写入的时候会自动转换回来

           }

           return -1;

      }

      public void myClose()throws IOException

      {

           in.close();

      }

}

怎么将键盘录入的数据存储到一个文件中?

读取键盘录入。

System.out:对应的是标准输出设备,控制台。

System.in:对应的标准输入设备:键盘。

import java.io.*;

class  ReadIn

{

      public static void main(String[] args) throws IOException

      {

           InputStream in = System.in;//System.in对应的是输入设备。建立一个字符输入流对象in,用来接收键盘输入的字节

           StringBuilder sb = new StringBuilder();//建立字符串数组

           while (true)

           {

                 int ch = in.read();//ch判断read返回值

                 if (ch==13)//当为13,就是\r的时候,继续向下执行

                      continue;

                 if(ch == 10)//当为10,就是\n的时候

                 {

                      String s= sb.toString();//sb转换为字符串形式返回给s

                      if("over".equals(s))//如果s的内容是字符串over

                            break;//那么终止循环。

                      System.out.println(s.toUpperCase());//不是over,那么就输出s的大写形式

                      sb.delete(0.sb.length());//如果不执行这个命令,每次输入的都会叠加。这条代码的作用就是每次输出后清空sb的内容。用delete。(集合才用clear()

                 }

                 else

                      sb.append((char)ch);//否则将ch转换成字节形式加入到sb

                

           }

           /*

           int ch = 0;

           while ((ch=in.read())!=-1)

           {

                 System.out.println(ch);

           }

           in.close();

           int by = in.read();//intby值读取第一个字节,并把值赋给by

           int by1 = in.read();

           int by2 = in.read();

           System.out.println(by);//打印by

           System.out.println(by1);

           System.out.println(by2);//输入a,输出结果是97 13 10,因为a对应的是字节编码表97,而\r\n分别对应1310

           */

      }

}

转换流的特点:

字符流:

FileReader

FileWriter

BufferedReader

BufferedWriter

字节流:

FileInputStream

FileOutputStream

BufferedInputStream

BufferedOutputStream

通过刚才的键盘录入一行数据并打印其大写,发现其实就是读一行数据的原理。也就是readLine方法。能不能直接使用readLine方法来完成键盘录入的一行数据的读取呢?

readLine方法是字符流BufferedReader类中的方法。

而键盘录入的read方法是字节流InputStream的方法。

那么能不能将字节流转成字符流在使用字符流缓冲去的readLine方法呢?

import java.io.*;

class  TransStreamDemo

{

      public static void main(String[] args) throws IOException

      {

           //InputStream in = System.in;

           //InputStreamReader isr = new InputStreamReader(in);//建立InputStreamReader对象 isr,将输入流in转换成字符流对象

           //BufferedReader bufr = new BufferedReader(isr);//建立缓冲区

           //上面三句话可以变成一句话

           BufferedReader bufr = new BufferedReader(newInputStreamReader(System.in));//这句话一定要记住,利用键盘输入就是这个指令

           //OutputStream out = System.out;

           //OutputStreamWriter osw= new OutputStreamWriter(out);

           BufferedWriter bfwr = new BufferedWriter(newOutputStreamWriter(System.out));

           String line = null;

           while ((line=bufr.readLine())!=null)//将输入的字符串转变大写

           {

                 osw.write(line.toUpperCase());

                 bfwr.newLine();//只有在缓冲区才有readline这个函数,所以上面建立一个缓冲区

                 osw.flush();//每次写入之后,要刷新流,不然输出时没有字符串导入,输出为空

           }

           bufr.close();

      }

}

流操作的基本规律:

最痛苦的就是流对象有很多,不知道该用哪一个。

通过三个明确来完成。

1,明确源和目的。

      源:输入流。InputStream  Reader

      目的:输出流。OutputStream  Writer

2,操作的数据是否是纯文本。

      是:字符流。

      不是:字节流。

3,当体系明确后,在明确要使用哪个具体的对象。

      通过设备来进行区分:

      源设备:内存,硬盘。键盘

      目的设备:内存,硬盘,控制台。

练习:

1,将一个文本文件中数据存储到另一个文件中。复制文件。

      源:因为是源,所以使用读取流。 Reader

      是不是操作文本文件。

      是!这时就可以选择FileReader

      这样体系就明确了。

 

      接下来明确要使用该体系中的哪个对象。

      明确设备:硬盘。上一个文件。

      Reader体系中可以操作文件的对象是 FileReader

 

      是否需要提高效率:是!。加入Reader体系中缓冲区 BufferedReader.

      FileReader fr = new FileReader("a.txt");

      BufferedReader bufr = new BufferedReader(fr);

 

      目的:OutputStream Writer

      是否是纯文本。

      是!Writer

      设备:硬盘,一个文件。

      Writer体系中可以操作文件的对象FileWriter

      是否需要提高效率:是!。加入Writer体系中缓冲区 BufferedWriter

      FileWriter fw = new FileWriter("b.txt");

      BufferedWriter bufw = new BufferedWriter(fw);

2,需求:将键盘录入的数据保存到一个文件中。

      这个需求中有源和目的都存在。

      那么分别分析

      源:InputStream Reader

      是不是纯文本?是!Reader

     

      设备:键盘。对应的对象是System.in.

      不是选择Reader吗?System.in对应的不是字节流吗?

      为了操作键盘的文本数据方便。转成字符流按照字符串操作是最方便的。

      所以既然明确了Reader,那么就将System.in转换成Reader

      用了Reader体系中转换流,InputStreamReader

 

      InputStreamReader isr = new InputStreamReader(System.in);

 

      需要提高效率吗?需要!BufferedReader

      BufferedReader bufr = new BufferedReader(isr);

      目的:OutputStream  Writer

      是否是存文本?是!Writer

      设备:硬盘。一个文件。使用 FileWriter

      FileWriter fw = new FileWriter("c.txt");

      需要提高效率吗?需要。

      BufferedWriter bufw = new BufferedWriter(fw);

转换流最重要的地方是将字节转换成字符时,可以转换成指定的码表

扩展一下,想要把录入的数据按照指定的编码表(utf-8),将数据存到文件中。

      目的:OutputStream  Writer

      是否是存文本?是!Writer

      设备:硬盘。一个文件。使用 FileWriter

      但是FileWriter是使用的默认编码表。GBK.    

但是存储时,需要加入指定编码表utf-8。而指定的编码表只有转换流可以指定。

      所以要使用的对象是OutputStreamWriter

      而该转换流对象要接收一个字节输出流。而且还可以操作的文件的字节输出流。FileOutputStream

      OutputStreamWriter osw = new OutputStreamWriter(newFileOutputStream("d.txt"),"UTF-8");

      需要高效吗?需要。

      BufferedWriter bufw = new BufferedWriter(osw);

      所以,记住。转换流什么使用。字符和字节之间的桥梁,通常,涉及到字符编码转换时,需要用到转换流。

 2  装饰设计模式 

装饰设计模式

什么是装饰设计模式?

装饰和继承的区别?

装饰设计模式的特点?

装饰设计模式:

简述:当想对已有对象进行功能增强是,可定义类:将已有对象传入,基于已有对象的功能,并提供加强功能,那么自定义的该类称之为装饰类。即对原有类进行了优化。

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

装饰和继承的区别:

1)装饰模式比继承要灵活,通过避免了继承体系的臃肿,且降低了类与类间的关系。

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

3)从继承结构转为组合结构。

注:在定义类的时候,不要以继承为主;可通过装饰设计模式进行增强类功能。灵活性较强,当装饰类中的功能不适合,可再使用被装饰类的功能。

        要继承相应的父类,就需要将所有的抽象方法实现,或交给子类实现。其中MyBufferedReader的例子就是最好的装饰设计模式的例子,就是BufferedReader的增强。

举例:

class Person  

{  

   public void chifan()  

   {  

      System.out.println("吃饭");  

   }  

}  

class SuperPerson  

{  

10   

11   private Person p;  

12   SuperPerson(Person p)  

13   {  

14     this.p=p;  

15   }  

16   public void superChifan()  

17   {  

18      System.out.println("开胃酒");  

19      p.chifan();  

20      System.out.println("甜点");  

21      System.out.println("吸根烟");  

22   }  

23     

24 }  

25 class PersonDemo  

26 {  

27    public static void main(String[] args)  

28    {  

29        Person p=new Person();  

30      //  p.chifan();  

31      SuperPerson sp=new SuperPerson(p);  

32        

33      sp.superChifan();  

34    }  

35      

36 }  

[java] view plaincopy

37 /* 

38 明白了BufferedReader类中特有方法readLine的原理后, 

39 可以自定义一个类中包含一个功能和readline一致的方法 

40 来模拟一下BufferedReader 

41 */  

42 import java.io.*;  

43   

44 class MyBufferedReader extends Reader  

45 {  

46     

47   //装饰设计模式  

48    private Reader r=null;  

49      

50    MyBufferedReader(Reader r)  

51    {  

52       this.r=r;  

53    }  

54    //可以一次读一行数据的方法  

55    public String myReadLine() throws IOException  

56    {  

57      //定义一个临时容器,员BufferedReader封装的是字符数组  

58      //为了演示方便,定义一个StringBulilder容器,因为最终还是要将数据变成字符串。  

59      StringBuilder sb=new StringBuilder();  

60      int ch=0;  

61      while((ch=r.read())!=-1)  

62      {  

63        if(ch=='\r')  

64        continue;  

65        if(ch=='\n')  

66         return sb.toString();  

67        else  

68        sb.append((char)ch);  

69      }  

70      //如果没有遇到\nsb中而且有数据的话也要返回  

71       if(sb.length()!=0)  

72         return sb.toString();  

73      return null;  

74    }  

75   /* 

76   覆盖类中的抽象方法 

77   */  

78   public int read(char[] cbuf,int off,int len)throws IOException  

79   {  

80     return r.read(cbuf,off,len);  

81   }  

82     

83   public void close() throws IOException  

84   {  

85       r.close();  

86   }  

87     

88   public void myClose() throws IOException  

89   {  

90       r.close();   

91   }  

92 }  

93   

94   

95   

96 class MyBufferedReaderDemo  

97 {  

98    public static void main(String[] args) throws IOException  

99    {  

100       FileReader fr=new FileReader("buf.txt");  

101         

102       MyBufferedReader myBuf=new MyBufferedReader(fr);  

103      

104       String line=null;  

105         

106       while((line=myBuf.myReadLine())!=null)  

107       {  

108         System.out.println(line);  

109       }  

110         

111       myBuf.myClose();  

112    }  

113      

114 }  

MyReader//专门用于读取数据的类。

      |--MyTextReader

           |--MyBufferTextReader

      |--MyMediaReader

           |--MyBufferMediaReader

      |--MyDataReader

           |--MyBufferDataReader

class MyBufferReader

{

      MyBufferReader(MyTextReader text)

      {}

      MyBufferReader(MyMediaReader media)

      {}

}

上面这个类扩展性很差。

找到其参数的共同类型。通过多态的形式。可以提高扩展性。

class MyBufferReader extendsMyReader

{

      private MyReader r;

      MyBufferReader(MyReader r)

      {}

}   

MyReader//专门用于读取数据的类。

      |--MyTextReader

      |--MyMediaReader

      |--MyDataReader

      |--MyBufferReader

以前是通过继承将每一个子类都具备缓冲功能。那么继承体系会复杂,并不利于扩展。

现在优化思想。单独描述一下缓冲内容。将需要被缓冲的对象。传递进来。也就是,谁需要被缓冲,谁就作为参数传递给缓冲区。

这样继承体系就变得很简单。优化了体系结构。

装饰模式比继承要灵活。避免了继承体系臃肿。而且降低了类于类之间的关系。

装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。

所以装饰类和被装饰类通常是都属于一个体系中的。

自己的语言描述:继承太臃肿,复杂。利用装饰设计模板,把原来的继承结构变成组合结构,这样多出来的一个类就可以实现前面3个类共性功能,同时将一些新的功能封装到自身里面以达到加强的作用,有继承结构变成组合结构,灵活性强,而且降低了类与类之间的关系。

自定义装饰类

如何自定义?

自定义装饰类只需要继承父类,如Reader,将原有的函数覆写并修改其函数内容即可

      public int read(char[] cbuf, int off, int len) throwsIOException

      {

           return r.read(cbuf,off,len) ;

      }

      public void close()throws IOException

      {

           r.close();

      }

LineNumberReader的用法?原理代码是什么?

LineNumberReader就是一个装饰类,在BufferedReader的基础之上,添加了编辑行号的功能

import java.io.*;

class LineNumberReaderDemo //BufferedReader的基础之上,添加了编辑行号的功能,LineNumberReader

{

      public static void main(String[] args) throws IOException

      {

           FileReader fr = new FileReader("装饰与继承.java");

           LineNumberReader lnr = newLineNumberReader(fr);

           String line = null;

           lnr.setLineNumber(100);//LineNumber中自带的函数setLineNumber(),可以设置当前行号。设置100就从100开始输出

            while((line=lnr.readLine())!=null)

           {//getLineNumber()获取行号。

                 System.out.println(lnr.getLineNumber()+":"+line);

           }

           lnr.close();

      }

}

 3  LineNumberReader 

BufferedReader中有个直接的子类LineNumberReader,其中有特有的方法获取和设置行号:setLineNumber()getLineNumber()

原理:LineNumberReader中有一个计数器,定义一个Reader流对象,当读到流对象的时候才能进行行号的添加

原理例子:

import java.io.*;

class MyLineNumberReaderextends MyBufferedReader//建立一个类,可以实现LineNumberReader的功能

{//因为LineNumberReader继承了BufferedReader,并且覆写了readline()方法,可以推测出通过覆写该方法来装饰BufferedReader得到LineNumberReader,所以MyLineNumberReader也可以继承MyBufferedReader来简化代码

      private int lineNumber;//私有化lineNumber可以用来记录行数。FileReader r不应再定义因为父类中有,可以直接拿来用

      public void setLineNumber(int lineNumber)

      {

           this.lineNumber = lineNumber;//定义setLineNumber,可以将setLineNumber()中的对象赋值给本类变量lineNumber

      }

      public int getLineNumber()//getLineNumber()获得本类中lineNumber,返回值为int

      {

           return lineNumber;

      }

      MyLineNumberReader (FileReader r)//构造函数

      {

           super(r);//直接调用父类中的构造函数

      }

      public String myReadLine()throws IOException//建立myReadLine(),实现可以一次读一行数据的方法。

      {    //定义一个临时容器。原BufferReader封装的是字符数组。

           //为了演示方便。定义一个StringBuilder容器。因为最终还是要将数据变成字符串。

           lineNumber++;//每次调用myReadLine()函数,linenumber就自加一次

           return super.myReadLine();//返回父类中的myReadLine()函数方法值,简化了代码。注意是返回!

      }

}

class MyLineNumberReaderDemo

{

      public static void main(String[] args) throws IOException

      {

           FileReader fr = new FileReader("装饰与继承.java");//源文件与流关联

           MyLineNumberReader mylnr = new MyLineNumberReader(fr);//使用自己的方法来读取fr

           String line = null;

           mylnr.setLineNumber(100);//初始设置LineNumber就为100,这样LineNumber100就开始计数了。

           while ((line=mylnr.myReadLine())!=null)

           {

                 System.out.println(mylnr.getLineNumber()+":"+line);//输出LineNumber的数值和line

           }

           mylnr.myClose();//使用自己的函数关闭流

      }

}

第一一个自己的类:

示例:

[java] view plaincopy

115 import java.io.*;  

116   

117 class MyLineNumberReader  extends MyBufferedReader  

118 {    

119    private Reader r;  

120    private int lineNumber;  

121    MyLineNumberReader(Reader r)  

122    {  

123       super(r);  

124    }  

125    public String myReadLine() throws IOException  

126    {  

127      

128      lineNumber++;   

129      return super.myReadLine();  

130    }  

131      

132    public void setLineNumber(int lineNumber)  

133    {   

134       this.lineNumber=lineNumber;  

135    }  

136    public int getLineNumber()  

137    {  

138       return lineNumber;  

139    }  

140 }  

141   

142 /* 

143 class MyLineNumberReader  

144 { 

145    private Reader r; 

146    private int lineNumber; 

147    MyLineNumberReader(Reader r) 

148    { 

149       this.r=r; 

150    } 

151    public String myReadLine() throws IOException 

152    { 

153     

154      lineNumber++;  

155      StringBuilder sb=new StringBuilder(); 

156      int ch=0; 

157       

158      while((ch=r.read())!=-1) 

159      { 

160        if(ch=='\r') 

161          continue; 

162        if(ch=='\n') 

163        return sb.toString(); 

164        else 

165        sb.append((char)ch); 

166      } 

167      if(sb.length()!=0) 

168         return sb.toString(); 

169      return null; 

170    } 

171     

172    public void setLineNumber(int lineNumber) 

173    {  

174       this.lineNumber=lineNumber; 

175    } 

176    public int getLineNumber() 

177    { 

178       return lineNumber; 

179    } 

180     

181    public void myClose()throws IOException 

182    { 

183      r.close(); 

184    } 

185     

186 } 

187 */  

188 

189 class MyLineNumberReaderDemo  

190 {  

191    public static void main(String[] number) throws IOException  

192    {  

193        FileReader fr=new FileReader("copyTextByBuf.java");  

194          

195        MyLineNumberReader mylnr=new MyLineNumberReader(fr);  

196          

197        String line=null;  

198        mylnr.setLineNumber(100);  

199        while((line=mylnr.myReadLine())!=null)  

200        {  

201          System.out.println(mylnr.getLineNumber()+"::"+line);  

202        }  

203         mylnr.myClose();  

204    }    

205 }  

字符流 字节流 总结

1. 文件的读取方式

  |-- FileReader这个对象读取文件,文本文件

  |-- 通过这个对象的read()方法来实现,文件结束返回-1

  |-- 通过这个对象的read(buf[])来实现,读一批的效果,提高效率

                返回值,就是数组存储有效字符的个数

                

2. 通过IO技术对文本文件进行复制

  |-- 读取文件对象

  |-- 写入文件对象

  |-- 读一个写一个

  |-- 读一批写一批,利用的是数组形式来完成

  |-- 两个复制的案例,一个是用数组,一个不用,用数组的必须要会

  

3. 输出流的缓冲区

  |-- BufferedWriter,提高输出流效率

  |-- 建立缓冲区对象的时候,需要传递输出流对象,为的是提高次输出流的效率

  |-- newLine()写一个换行,跨平台性

  

4. 输入流的缓冲区

  |-- BufferedReader ,提高输入流的效率

  |-- 建立缓冲区对象的时候,需要传递输入流对象,为的是提高次输入流的效率

  |-- readLine()读取一行,返回的是字符串,读到结尾返回null,不返回换行符

  

5. 利用缓冲区对文本文件进行复制  *****

  |-- 需要输出流对象,输入流对象

  |-- 需要缓冲输出流对象,缓冲输入流对象

  |-- 读一行,写一个,写一个换行

  |-- 异常处理

  

6.IO对象小结

  |-- 字符流对象

    |-- 输出流

      |-- Write

        |-- FileWriter

        |-- BufferWriter

    |-- 输入流

      |-- Reader

        |-- FileReader

        |-- BufferedReader

        

7. 装饰设计

  |-- 对已经有的对象的0功能,进行增强,额外的为对象添加功能

  |-- 已经有了人对象,吃饭的功能已经落后,需要增加功能

  |-- 为人这个对象,对他的吃饭的功能,进行增强,搞了一个类去增强人对象的吃饭功能

  |-- 增强功能的类,称为人类的装饰类

  |-- 装饰设计模式,发现原有的功能已经不能满足现在的需求,搞个装饰类,对原有的对象进行装饰

  

8. 继承和装饰模式的区别

  |-- 继承是面向对象三大特征之一

  |-- 装饰模式,是为了解决现实中的问题而产生的

  

  |-- 读取文本文件 TextReader

     |--BufferedTextReader  extends TextReader

  |-- 读取图片文件 PicReader

     |-- BufferedPicReader extends PicReader

  |-- 读取网络数据 NetReader

     |-- BufferedNetReader extends NetReader

  |-- 读取视频数据 VideReader

     |-- BufferedVideoReader extens VideoReader

  

  |-- 解决继承体系过于臃肿,采用装饰模式

  |-- Reader

    |-- TextReader

    |-- PicReader

    |-- NetReader

    |-- VideReader

    |-- MP3Reader 

    |-- BufferedReader(Reader r) extends Reader

   

  |-- 继承体系臃肿而且庞大,灵活性还差

  |-- 装饰设计模式,体系简洁的多 灵活性好

  

9. 自己定义装饰类,装饰Reader类*****

  |-- 自己写一个readLine()方法

     |-- 返回的是字符串

     |-- 返回的是文本中一行,但是没有换行符

  

10. 字节流  -- 什么类型文件都可以操作

   |-- 输出流基类 OutputStream

     |-- FileOutputStream对文件进行写入操作,写入的是一个字节数组

   |-- 输入流基类 InputStream

     |-- FileInputStream对文件进行读取,用字节数组来实现缓冲,提高效率

     

   read()  write() 字节数组  "".getBytes()

   |-- 读一个写一个的复制文件

   |-- 利用数组缓冲来复制文件

   |-- 作业,利用API中字节流缓冲区对象,复制文件

  

  

  

  

  

  

 

 

 

本篇博文结束!




                                                                                                   @感谢老师的辛苦批阅

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值