• IO流2(装饰设计模式,LineNumberReader,InputStream,OutputStream,InputStreamReader)


    装饰设计模式:

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

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

    例如:

      1: import java.io.*;
    
      2: 
    
      3: /*
    
      4: 使用装饰设计模式,比较灵活,降低了类与类之间的关系
    
      5: */
    
      6: class Person 
    
      7: {
    
      8: 	public void chifan()
    
      9: 	{
    
     10: 		System.out.println("吃饭");
    
     11: 	}
    
     12: }
    
     13: 
    
     14: class SuperPerson
    
     15: {
    
     16: 	private Person p;
    
     17: 
    
     18: 	//将Person类的对象通过SuperPerson的构造函数传进来,这样就可以在
    
     19: 	//SuperPerson类中使用Person对象的方法,并且可以对Person对象的功能进行增强
    
     20: 	SuperPerson(Person p)
    
     21: 	{
    
     22: 		this.p=p;
    
     23: 	}
    
     24: 
    
     25: 	public void superChifan()
    
     26: 	{
    
     27: 		System.out.println("开胃酒");
    
     28: 		p.chifan();
    
     29: 		System.out.println("甜点");
    
     30: 	}
    
     31: 
    
     32: }
    
     33: 
    
     34: class PersonDemo
    
     35: {
    
     36: 	public static void main(String[] args)
    
     37: 	{
    
     38: 		Person p=new Person();
    
     39: 		SuperPerson sp=new SuperPerson(p);
    
     40: 
    
     41: 		sp.superChifan();
    
     42: 	}
    
     43: }
    
     44: 
    
     45: 
    
     46: 
    
     47: 

    MyReader  专门用来读取数据的类

          |---MyTextReader

                |---MyBufferedTextReader

          |---MyMediaReader

                |---MyBufferedMediaReader

    MyReader有很多子类,例如MyTextReader和MyMediaReader,但是单个读取的效率太低,因此又出现了使用缓冲区的子类,加强形式,但是这样MyReader每增加一个子类,就需要增加一个加强形式。这样扩展性太差。

    如果想Buffer功能单独写成一个类呢,那么有

    class  MyBufferReader

    {

          MyBufferedReader(MyTextReader  mytext)  {   }

          MyBufferedReader(MyMediaReader mymedia)  {   }

          ………….

    }

    这样的话,MyReader每增加一个子类,MyBufferReader就要增加一个构造方法,扩展性也很差。那么找其参数的共同类型,改写成多态的形式,这样就提高了扩展性。

    class   MyBufferedReader   extends  MyReader

    {

             MyBufferReader(MyReader   r)  {    }

    }

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

    MyReader 专门用来读取数据的类

          |---MyTextReader

          |---MyMediaReader

          |---MyBufferedReader


    LineNumberReader:(BufferedReader的子类)

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

      1: import java.io.*;
    
      2: 
    
      3: class MyLineNumberReader
    
      4: {
    
      5: 	private FileReader r;
    
      6: 	private int num=0;
    
      7: 	MyLineNumberReader(FileReader r)
    
      8: 	{
    
      9: 		this.r=r;
    
     10: 	}
    
     11: 
    
     12: 	public String myReadLine()throws IOException
    
     13: 	{
    
     14: 		num++;
    
     15: 		StringBuilder sb=new StringBuilder();
    
     16: 		int ch=0;
    
     17: 		while((ch=r.read())!=-1)
    
     18: 		{
    
     19: 			if(ch=='\r')
    
     20: 				continue;
    
     21: 			if(ch=='\n')
    
     22: 				return sb.toString();
    
     23: 			else sb.append((char)ch);
    
     24: 		}
    
     25: 
    
     26: 		if(sb.length()!=0)
    
     27: 			return sb.toString();
    
     28: 
    
     29: 		return null;
    
     30: 
    
     31: 	}
    
     32: 
    
     33: 	//设置行号
    
     34: 	public void mySetLineNumber(int num)
    
     35: 	{
    
     36: 		this.num=num;
    
     37: 	}
    
     38: 
    
     39: 	//获取行号
    
     40: 	public int myGetLineNumber()
    
     41: 	{
    
     42: 		return num;
    
     43: 	}
    
     44: 
    
     45: 	public void myClose()throws IOException
    
     46: 	{
    
     47: 		r.close();
    
     48: 	}
    
     49: 
    
     50: 
    
     51: }
    
     52: 
    
     53: 
    
     54: 
    
     55: 
    
     56: class MyLineNumberReaderDemo 
    
     57: {
    
     58: 	public static void main(String[] args) throws IOException
    
     59: 	{
    
     60: 		FileReader fr=new FileReader("MyBufferedReaderDemo.java");
    
     61: 		MyLineNumberReader mylnr=new MyLineNumberReader(fr);
    
     62: 
    
     63: 		String line=null;
    
     64: 		while((line=mylnr.myReadLine())!=null)
    
     65: 		{
    
     66: 			System.out.println(mylnr.myGetLineNumber()+":"+line);
    
     67: 		}
    
     68: 		mylnr.myClose();
    
     69: 
    
     70: 
    
     71: 	}
    
     72: }
    
     73: 

    字节流:

    需求,如果想要操作图片数据,这是需要使用到字节流。InputStream和OutputStream

      1: import java.io.*;
    
      2: 
    
      3: 
    
      4: class FileStream 
    
      5: {
    
      6: 	public static void writeFile()throws IOException
    
      7: 	{
    
      8: 		FileOutputStream fos=new FileOutputStream("fos.txt");
    
      9: 
    
     10: 		
    
     11: 		//字节流只可以写入字节或者字节数组,abcde为字符串,需要进行转换,getBytes()
    
     12: 		//getBytes()方法,将String编码为byte序列,并将结果存在一个新的byte数组中
    
     13: 		fos.write("abcde".getBytes());
    
     14: 
    
     15: 		//如果没有使用到指定的缓冲区,是不需要缓冲的,但是需要关闭资源
    
     16: 		fos.close();
    
     17: 	}
    
     18: 	
    
     19: 	//单个字节读取
    
     20: 	public static void readFile_1()throws IOException
    
     21: 	{
    
     22: 		FileInputStream fis=new FileInputStream("fos.txt");
    
     23: 
    
     24: 		int ch=0;
    
     25: 		while((ch=fis.read())!=-1)
    
     26: 		{
    
     27: 			System.out.println((char)ch);
    
     28: 		}
    
     29: 		fis.close();
    
     30: 	}
    
     31: 	
    
     32: 	//按字节数组来进行读取
    
     33: 	public static void readFile_2()throws IOException
    
     34: 	{
    
     35: 		FileInputStream fis=new FileInputStream("fos.txt");
    
     36: 
    
     37: 		byte[] buf=new byte[1024];
    
     38: 		int len=0;
    
     39: 
    
     40: 		while((len=fis.read(buf))!=-1)
    
     41: 		{
    
     42: 			System.out.println(new String(buf));
    
     43: 		}
    
     44: 
    
     45: 		fis.close();
    
     46: 	}
    
     47: 
    
     48: 	public static void readFile_3()throws IOException
    
     49: 	{
    
     50: 		FileInputStream fis=new FileInputStream("fos.txt");
    
     51: 
    
     52: 		//available()方法,返回值为文件中的字节数,包括换行符,这样可以定义一个刚好的缓冲区,不需要循环
    
     53: 
    
     54: 		byte[] buf=new byte[fis.available()];
    
     55: 
    
     56: 		fis.read(buf);
    
     57: 
    
     58: 		System.out.println(new String(buf));
    
     59: 
    
     60: 		fis.close();
    
     61: 	}
    
     62: 
    
     63: 		
    
     64: 
    
     65: 	public static void main(String[] args) throws IOException
    
     66: 	{
    
     67: 		readFile_3();
    
     68: 	}
    
     69: }
    
     70: 

    练习:复制一张图片

      1: import java.io.*;
    
      2: 
    
      3: class PictureCopy 
    
      4: {
    
      5: 	public static void main(String[] args) 
    
      6: 	{
    
      7: 		FileInputStream fis=null;
    
      8: 		FileOutputStream fos=null;
    
      9: 		try
    
     10: 		{
    
     11: 			fis=new FileInputStream("IMG_0696.jpg");
    
     12: 			fos=new FileOutputStream("abc.jpg");
    
     13: 			byte[] buf=new byte[1024];
    
     14: 
    
     15: 			int len=0;
    
     16: 			while((len=fis.read(buf))!=-1)
    
     17: 			{
    
     18: 				fos.write(buf);
    
     19: 			}
    
     20: 			
    
     21: 		}
    
     22: 		catch (IOException e)
    
     23: 		{
    
     24: 		    System.out.println("...");
    
     25: 
    
     26: 		}
    
     27: 		finally
    
     28: 		{
    
     29: 			try
    
     30: 			{
    
     31: 				fis.close();
    
     32: 			}
    
     33: 			catch (IOException e)
    
     34: 			{
    
     35: 				System.out.println("关闭读取资源失败");
    
     36: 
    
     37: 			}
    
     38: 			try
    
     39: 			{
    
     40: 				fos.close();
    
     41: 			}
    
     42: 			catch (IOException e)
    
     43: 			{
    
     44: 				System.out.println("关闭写入资源失败");
    
     45: 
    
     46: 			}
    
     47: 		}
    
     48: 	}
    
     49: }
    
     50: 

    MP3的复制,通过缓冲区:

      1: class CopyMP3 
    
      2: {
    
      3: 	public static void main(String[] args) throws IOException
    
      4: 	{
    
      5: 		//定义一个读取流对象,读取目标文件中的数据
    
      6: 		BufferedInputStream bufis=new BufferedInputStream(new FileInputStream("c:\\0.mp3"));
    
      7: 
    
      8: 		//定义一个输出流对象,用来将读取到的数据写入到目的文件中去
    
      9: 		BufferedOutputStream bufos=new BufferedOutputStream(new FileOutputStream("c:\\1.mp3"));
    
     10: 
    
     11: 		int by=0;
    
     12: 		byte[] buf=new byte[1024];
    
     13: 		while((by=bufis.read(buf))!=-1)
    
     14: 		{
    
     15: 			bufos.write(by);
    
     16: 		}
    
     17: 
    
     18: 		bufis.close();
    
     19: 		bufos.close();
    
     20: 
    
     21: 	}
    
     22: }
    
     23: 

    自定义字节流缓冲区:

      1: class MyBufferedInputStream 
    
      2: {
    
      3: 	private InputStream in;
    
      4: 	//定义一个byte型的数组,用于存储数据
    
      5: 	private byte[] buf=new byte[1024];
    
      6: 	//count为计数器,pos为数组的指针
    
      7: 	private int pos=0,count=0;
    
      8: 
    
      9: 	MyBufferedInputStream(InputStream in)
    
     10: 	{
    
     11: 		this.in=in;
    
     12: 	}
    
     13: 
    
     14: 	//一次读取一字节,从
    
     15: 	public int myRead() throws IOException
    
     16: 	{
    
     17: 		//通过in来读取硬盘上的数据,并且存储到buf中
    
     18: 		if(count==0)
    
     19: 		{
    
     20: 			count=in.read(buf);
    
     21: 			if(count<0)
    
     22: 				return -1;
    
     23: 			pos=0;
    
     24: 			byte b=buf[pos];
    
     25: 			count--;
    
     26: 			pos++;
    
     27: 
    
     28: 			return b&255;
    
     29: 		}
    
     30: 		else if(count >0)
    
     31: 		{
    
     32: 			byte b=buf[pos];
    
     33: 			count--;
    
     34: 			pos++;
    
     35: 
    
     36: 			return b&255;
    
     37: 		}
    
     38: 		return -1;
    
     39: 	}
    
     40: 
    
     41: 	public void myClose()throws IOException
    
     42: 	{
    
     43: 		in.close();
    
     44: 	}
    
     45: 
    
     46: }
    
     47: 
    
     48: /*
    
     49: why b&255?
    
     50: 
    
     51: 若数据文件的第一个数据恰好是1111 1111
    
     52: 提升成了int类型以后,数据值为-1
    
     53: 
    
     54: 是-1的原因是因为在8个1前面补得为1,如果在前边补0,即可以保留原字节数据不变,又可以避免-1的出现
    
     55: 
    
     56: 1111 1111 1111 1111 1111 1111 1111 1111
    
     57: 0000 0000 0000 0000 0000 0000 1111 1111 
    
     58: 
    
     59: 
    
     60: 0000 0000 0000 0000 0000 0000 1111 1111 
    
     61: 提升为int型后,多占了内存,write方法写入时,将前面的舍弃,只保留后8位
    
     62: 
    
     63: */

    读取键盘录入:

    需求:通过键盘录入数据,当录入一行数据,就将该行数据进行打印,如果录入的数据为over,那么停止录入

      1: class InputStreamDemo 
    
      2: {
    
      3: 	public static void main(String[] args) 
    
      4: 	{
    
      5: 		InputStream in=System.in;
    
      6: 		StringBuilder sb=new StringBuilder();
    
      7: 		while(true)
    
      8: 		{
    
      9: 			int ch=in.read();
    
     10: 			if(ch=='\r')
    
     11: 				continue;
    
     12: 			if(ch=='\n')
    
     13: 			{
    
     14: 				String s=sb.toString();
    
     15: 				if("over".equals(s))
    
     16: 					break;
    
     17: 				System.out.println(s.toUpperCase());
    
     18: 				//每次录入一行数据,就将该行数据进行打印以后,应该将存在StringBuilder里面的
    
     19: 				//内容清空,下次录入时,才不会有下一次的数据
    
     20: 
    
     21: 				sb.delete(0,sb.length());
    
     22: 
    
     23: 			}
    
     24: 			else sb.append((char)ch);
    
     25: 		}
    
     26: 	}
    
     27: }
    
     28: 
    
     29: /*
    
     30: 以上代码即为读一行数据的原理,即readLine()方法
    
     31: 那能不能直接用readLine方法来完成键盘录入的一行数据的读取呢?
    
     32: 
    
     33: 但是readLine方法是字符流BufferedReader类中的方法,而键盘录入的read方法,是字节流InputStream的方法
    
     34: 那么能不能将字节流转换成字符流,而使用字符流缓冲区的readLine方法呢?
    
     35: 
    
     36: 使用InputStreamReader类
    
     37: 
    
     38: */
      1: public void method()throws Exception
    
      2: 	{
    
      3: 		InputStream in=System.in;
    
      4: 
    
      5: 		//将字节流对象转成字符流对象,使用转换流
    
      6: 		InputStreamReader isr=new InputStreamReader(in);
    
      7: 		//为了提高效率,将字符串进行缓冲区技术高效操作,使用BufferedReader
    
      8: 		BufferedReader bufr=new BufferedReader(isr);
    
      9: 
    
     10: 		String line=null;
    
     11: 		while((line=bufr.readLine())!=null)
    
     12: 		{
    
     13: 			if("over".equals(line))
    
     14: 				break;
    
     15: 			System.out.println(line.toUpperCase());
    
     16: 		}
    
     17: 
    
     18: 		bufr.close();
    
     19: 	}
  • 相关阅读:
    js 正则表达式 test match exec三个方法的异同
    网页使用MD5加密
    解决Google地图和字体api无法加载的问题(转)
    Javascript 的addEventListener()及attachEvent()区别分析
    get与post的区别
    清除浮动的几种方法
    zoom属性(IE私有属性)
    class,id和name的区别
    深夜偷精之反射函数
    jQuery和js区别
  • 原文地址:https://www.cnblogs.com/mandy920213/p/3527332.html
Copyright © 2020-2023  润新知