------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! ----

来源:互联网 发布:陌游为什么网络异常 编辑:程序博客网 时间:2024/03/29 05:26

黑马程序员 IO流 缓冲区、装饰模式

1   .IO流,创建一个对象,该对象一被初始化就必须明确要操作的文件。文件被传见到指定目录下,如果有同名文件就会被覆盖。fw.flush()刷新流对象中的缓冲数据,将数据刷到目的地,flush刷新后流可以继续使用,close刷新后流会关闭。


   

2.字符流的缓冲区

缓冲区的出现是,为了提高流的操作效率而出现的。所以在创建缓冲区前,必须先有流对象。字符读取流缓冲区提供了一个一次毒一行的方法readline,方便于文本数据的获取,当返回null时,表示读到文本末尾,readline方法返回的时候只返回回车符之前的数据,并不返回回车符。

字符流的缓冲区

对应类:

BufferedWriter

BufferedReader

缓冲区的出现是为了提高流的操作效率,所以在创建缓冲区之前必须要先有流对象。将需要被提高效率的流对象作为参数传递给缓冲区的构造函数。

关闭缓冲区,就是在关才缓冲区中的流对象。

newline():换行

FileWriter fw = FileWriter(“D:\\aa.txt”);

BufferedWriter bw = BufferedWriter(fw);

bw.write(“adfdsafdsa”);

bw.newline();

bw.write(“fdsafsda”);

bw.close();

 

BufferedReader

readLine():读一行

FileReader fr = new FileReader(“d:\\txt.txt”);

BufferedReader br = new BufferedReader(fr);

String str=null;

while((str=br.readLine())!=null){

out.print(str);

}

br.close();

 

缓冲区的复制文件

BufferedWriter bw = null;

BufferedReader br = null;

 

try{

        bw = newBufferedWriter(new FileWriter(“D:\\aaa_copy.txt”));

        br = newBufferedReader(new FileReader(“D:\\aaa.txt”));

       

        String line = null;

        while((line=br.readLine())!=null){

               bw.write(line);

               bw.newLine();

               bw.flush();

}

}

装饰设计模式:

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

 

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

 

装饰和继承的区别:

例:

MyReader

        |--MyTextReader

        |--MyTextReader

变为:

MyReader

        |--MyTextReader

        |--MyTextReader

        |--MyBuffereReader

装饰模式比继承要灵活,避免了继承体系臃肿,而且降低了类与类之间的关系。装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强的功能。所有装饰类和被装饰类通常是都属于一个体系中的。

import java.io.*;

class MyLineNumberReader{
 
 private FileReader fr;
 private int LineNumber=11;
 
 MyLineNumberReader(FileReader fr ){
  
  this.fr = fr;
 }
 
 public String myReadLine()throws Exception{
  
  StringBuffer sb = new StringBuffer();
  int ch;
  while((ch=fr.read())!=-1){
   
   if(ch=='\r'){
    continue;
   }
   if(ch=='\n'){
    LineNumber++; 
    return sb.toString();
   }
   else{
    sb.append((char)ch);
   }
  }
  
  if(sb.length()!=0){
   System.out.println("+++++++++++++++++++++++++");
   return sb.toString();
  }
   
  return null;
 }
 
 public void setLineNumber(int LineNumber){
  
  this.LineNumber=LineNumber;
 }
 
 public int getLineNumber(){
  
  return LineNumber;
 }
 
 public void close()throws Exception{
  
  fr.close();
 }
}

class MyLineNumberDemo{
 
 public static void main(String[] args)throws Exception{
  
  FileReader fr = new FileReader("D:\\tmp\\aa_copy.txt");
  
  MyLineNumberReader lnr = new MyLineNumberReader(fr);
  
  lnr.setLineNumber(11);
  String str;
  while((str=lnr.myReadLine())!=null){
   
   System.out.println(lnr.getLineNumber()+":"+str);
  }
  
  lnr.close();
 }
}

 

LineNumberReader带行号的装饰类

getLineNumber();

setLineNumber();

 

自定义LineNumberReader

  FileReader fr = new FileReader("D:\\tmp\\aa_copy.txt");
  
  LineNumberReader lnr = new LineNumberReader(fr);
  
  lnr.setLineNumber(0);
  String str;
  while((str=lnr.readLine())!=null){
   
   System.out.println(lnr.getLineNumber()+":"+str);
  } 
  lnr.close();

 

 

字节流:

InputStream

OutputStream

 

FileInputStream

FileOutputStream

write(“abcd”.getBytes());//以单个字符存入

不需要用flush()方法刷新

 

FileInputStream fis = new FileInputStream(“aa.txt”);

byte[] buf = new byte[fis.available()];

fis.read(buf);

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

fis.close();

不建议使用此方式,因为考虑到文件比较大时,会发生内存溢出。

所以一般使用下面方式

 

FileInputStream fis = new FileInputStream(“aa.txt”);

byte[] buf = new byte[1024];

int num=0;

while((num=fis.read(buf))!=-1){

System.out.println(newString(buf,0,num));

}

 

复制一张图片

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

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

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

    关才资源。

 

字节流的缓冲区

BufferedOutputStream

BufferedInputStream

 

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

BufferedOntputStream bufos = new BufferedOntputStream(new FileOntputStream(“c:\\1_copy.mp3”));

int by=0;

while((by=bufis.read())!=-1){

        bufos.write(by);

}

 

 自定义字节流缓冲区

       import java.io.*;

      

       classMyBufferedInputStream{

              privateInputStream in;

              privatebyte[] buf = new byte[1024];

              private intpos=0,count=0;

              MyBufferedInputStream(InputStreamin){

                     this.in=in;

}

//一次读一个字节,从缓冲区(字节数组)获取。

publicint myRead(){

       //通过in对象读取硬盘上数据,并存储buf中。

       if(count==0){

              count = in.read(buf);

              if(count<0)

                     return -1;

              pos=0;

              byte b = buf[pos];

              count--;

              pos++;

              return b&255;

}elseif(count>0){

       byte b = buf[pos];

              count--;

              pos++;

              return b&255;

}

return-1;

}

publicvoid myClose(){

       in.close();

}

}

 

 

读取键盘录入

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

     System.in:对应的是键盘

 

InputStreamin = System.in;

int by =in.read();

System.out.println(by);

InputStreamin = System.in;

int ch=0;

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

       System.out.println(by);

}

InputStreamin = System.in;

StringBuildersb = new StringBuilder();

while(true){

       int ch=in.read();

       if(ch==’\r’)

              contine;

       if(ch==’\n’){

              String s = sb.String();

              if(“over”.equals(s))

                     break;

              System.out.println(s.toUpperCase());

              sb.delete(0,sb.length());

}else{

       sb.appen((char)ch);

}

}

               通过刚才的键盘录入一行数据并打印其大写,发现其实就是读一行数据的原理,也就是readLine方法。

       能不能直接使用readLine方法来完成键盘录入的一行数据的读取呢?

       readLine方法是BufferedReader类中的方法。

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

       那么将字节流转换成字符流再使用字符流缓冲区的readLine的方法。

       InputStreamReader:将字节流转换成字符流,在构造方法中传入字节流。

       OutputStreamWriter

       code:

       //获取键盘录入对象。

       //InputStream in = System.in;

       //将字节流对象转成字符流对象,使用转换流:InputStreamReader;

       //InputStreamReader isr = newInputStreamReader(in);

       //为了提高效率,将字符串进行缓冲区的高效操作,使用装饰类:BufferedReader;

       //BufferedReader byfr = newBufferedReader(isr);

       BufferedReader byfr = newBufferedReader(new InputStreamReader(System.in));

      

       //OutputStream out = System.out;

       //OutputStreamWriter osw = newOutputStreamWriter(out);

       //BufferedWriter bufw = newBufferedWriter(osw);

       BufferedWriter bufw = newBufferedWriter(new OutputStreamWriter(System.out));

      

       String line=null;

       while((line=bufr.read())!=null){

                     if(“over”.equals(line))

                            break;

                     osw.write (line.toUpperCase());

                     bufw.newLine();

                     osw.flush();

}

byfr.close();

 

         

1.     将键盘输入的数据写入到一个文件中,只需改上述代码中的目的由控制台改为文件。

       BufferedWriter bufw= new BufferedWriter(new OutputStreamWriter(new FileOutputStream(“out.txt”)));

       2.     将一个文件的数据打印在控制台上。

       BufferedReader bufr= new BufferedReader(new InputStreamReader(new FileInputStream(“copyPic.java”)));

      

       流操作的基本规律:

       流对象有很多,不知识该用哪一个。

       通过两个明确来完成。

    明确源和目的。

     源:输入流:InputStream      Reader

     目的:输出流:OutputStream              Writer

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

     是:字符流:Reader              Writer

     不是:字节流:InputStream          OutputStream

    当体系明确后,在明确要使用哪个具体的对象。通过设备来进行区分:

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

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

 

       需求:

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

源:InputStreamReader //因为是源,所以使用读取流,判断是不是操作文本文件,是!则选择Reader。这样体系就明确了。

接下来明确要使用该体系中的哪个对象。明确设备:硬盘上的一个文件。

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

是否需要提高效率,是!则加入Reader体系中的缓冲区:BufferedReader;

 

目的:OutputStreamWriter //目的是否是纯文本,是!则Writer。设备:硬盘上的一个文件。Writer体系中可以操作文件的对象是:FileWriter

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

 

    将键盘录入的数据保存到一个文件中。

源:InputStream Reader //判断是不是纯文件?是!则用Reader

设备:键盘,对应的对象是System.in ??? 不是选择Reader吗?System.in对应的不是字节流吗?为了操作键盘 的文本数据方便。转成字符流按照字符串操作是最方便的。所以既然明确了Reader,那么就将System.in转换成Reader

用到了Reader体系中的转换流,InputStreamReader

code:

InputStreamReader isr = new InputStreamReader(System.in);

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

BufferedReader bufr = new BufferedReader(isr);

 

目的:OutputStream Writer  //是否是纯文本,是!则用Writer

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

code:

FileWriter fw = new FileWriter(“a.txt”);

//提高效率?

BufferedWriter bufw = new BufferedWriter(fw);

 

扩展,想要把录入的数据按照指定的编码表存入,将数据存到文件中。

 

目的:OutputStream Writer  //是否是纯文本,是!则用Writer

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

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

 

但是存储时,需要加入指定编码表,而指定的编码表只有转换流可以指定。所以要使用的对象是OutputStreamWriter.而该转换对象要接收一个字节输出流,而且还可操作的文件的字节输出流。FileOutputStream

code:

OutputStreamWriterosw = new OutputStreamWriter(new FileOutputStream(“d.txt”),”UTF-8”);

需要高效吗?需要!

BufferedWriterbufw = new BuffereWriter(osw);

 

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

 

读取指定编码表的文件

InputStreamReader

 

      改变标准输入输出设备-不常用

       System.setIn(new FileInputStream(“a.txt”);

       System.setOut(newFileOutputStream(“b.txt”));

 

    系统日志文件

       catch(Exception e){

              Date d = newDate();

              SimpleDateFormatsdf = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);

              String s =sdf.format(d);

 

              PrintStreamps = new PrintStream(“exeception.log”)

              ps.println(s);

              System.setOut(ps);

              e.printStackTreace(System.out);

}

 

   打印系统信息

       Properties p =System.getProperties();

       //p.list(System.out);

       p.liset(newPrintStream(“systeminfo.txt”));


   

0 0
原创粉丝点击