java笔记-IO流-装饰设计模式、字节流

装饰设计模式:

当想要对已有的对象进行功能增强时,可以自定义类,将已有的对象传入,基于已有的对象,并提供加强功能,那么自定义的类就称为加强类。装饰类通常通过构造方法传递。

装饰类和继承的区别:

装饰模式比继承模式要灵活,而且降低了类与类之间的关系。

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

LineNumberReader实例

/*
 LineNumberReader Demo.
*/
import java.io.*;
class LineNumberDemo 
{
	public static void main(String[] args)
	{
		BufferedReader buf=null;
		LineNumberReader lineNumber=null;
		try{
			buf=new BufferedReader(new FileReader("buf.txt"));
			lineNumber=new LineNumberReader(buf);
			String str=null;
			while((str=lineNumber.readLine())!=null){
				System.out.println(lineNumber.getLineNumber()+"..."+str);
			}
		}
		catch(IOException e){
			throw new RuntimeException("read error.");
		}
		finally{
			try{
				if(lineNumber!=null){
					lineNumber.close();
				}
			}
			catch(Exception e){
				System.out.println(e);
			}
		}
	}
}
自定义LineNumberReader实例

/*
 重写LineNumber类,实现行号的显示和设置。
*/
import java.io.*;

class  MyLineNumberDemo
{
	public static void main(String[] args) 
	{
		FileReader fr=null;
		BufferedReader buf=null;
		//捕捉异常。
		try{
			fr=new FileReader("buf.txt");
			buf=new BufferedReader(fr);
			//使用自定义的MyLineNumber类。
			MyLineNumber myLine=new MyLineNumber(buf);
			String str=null;
			//设置行号。
			myLine.setLineNumber(100);
			//读取缓冲区中的数据。
			while((str=myLine.readLine())!=null){
				//获取行号并显示。
				System.out.println(myLine.getLineNumber()+"..."+str);
			}
		}
		catch(Exception e){
			System.out.println(e);	
		}
		finally{
			try{
				if(buf!=null)
					buf.close();
			}
			catch(Exception e){
				System.out.println(e);
			}
		}
	}
}
//自定义MyLineNumber类,显示和获取行号。
class MyLineNumber
{
	//将数据读取到缓冲区中。
	private BufferedReader bufr;
	//设置行号属性。
	private int lineNumber=0;
	//在构造函数中直接初始化操作的缓冲区。
	MyLineNumber(BufferedReader bufr){
		this.bufr=bufr;
	}
	//获取行号。
	public int getLineNumber(){
		return lineNumber;
	}
	//设置行号。
	public void setLineNumber(int num){
		this.lineNumber=num;
	}
	//关闭缓冲区并抛出异常。
	public void close()throws IOException{
		bufr.close();
	}
	//自定义一行行读取,并抛出异常。
	public String readLine()throws IOException{
		//每读取一行,行号自定增加。
		this.lineNumber++;
		//将读取到的行数据存储在字符串缓冲区中。
		StringBuilder sb=new StringBuilder();
		int ch=0;
		//依次读取字符,并判断是否达到行尾。
		while((ch=bufr.read())!=-1){
			//windows行尾由\r\n来确定。
			//读取到\r继续但不存储。
			if(ch=='\r')
				continue;
			//读取到\n直接将存储的行数据转化到字符串。
			if(ch=='\n')
				return sb.toString();
			//如果不是到行尾则将读取的字符存储到字符串缓冲区。
			else
				sb.append((char)ch);
		}
		//读取完成后,若最后一行不换行,此时ch!=\n,但字符串缓冲区中
		//仍有数据,需将该数据输出。
		if(sb.length()!=0)
			return sb.toString();
		return null;
	}
}

字节流

字节流的读取方式

import java.io.*;
class  FileInput
{
	public static void main(String[] args) throws Exception
	{
		//单个字节逐个读取。
		readFile_1();
		//按照固定长度读取。
		//建议采用该方法。
		readFile_2();
		//根据要读取的字节长度读取。
		//由于读取的文件大小不定,有可能内存溢出,该方法慎用。
		readFile_3();
	}
	//单个字节逐个读取。
	public static void readFile_1() throws Exception{
		FileInputStream fop=new FileInputStream("buf.txt");
		int by=0;
		while((by=fop.read())!=-1){
			System.out.print((char)by);
		}
		fop.close();
	}
	//按照固定的长度读取字节数。
	public static void readFile_2() throws Exception{
		FileInputStream fop=new FileInputStream("buf.txt");
		byte[] by=new byte[1024];
		int len=0;
		while((len=fop.read(by))!=-1){
			System.out.print(new String(by,0,len));
		}
		fop.close();
	}
	//按照操作文本的长度读取字节数
	public static void readFile_3() throws Exception{
		FileInputStream fop=new FileInputStream("buf.txt");
		byte[] by=new byte[fop.available()];
		fop.read(by);
		System.out.print(new String(by));
		fop.close();
	}
}
图片的复制

思路:

1.用字节读取流和要读取的图片关联

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

3.循环读取,直到将图片数据读取完毕

4.关闭资源(异常处理)

/*
 复制图片
*/
import java.io.*;
class  CopyPicture
{
	public static void main(String[] args) 
	{
		FileInputStream fis=null;
		FileOutputStream fos=null;
		try{
			fis=new FileInputStream("1.jpg");
			fos=new FileOutputStream("1copy.jpg");
			byte[] picData=new byte[1024];
			int len=0;
			while((len=fis.read(picData))!=-1){
				fos.write(picData,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音频文件(方式一)
/*
 复制MP3音频文件
*/
import java.io.*;
class copyMp3 
{
	public static void main(String[] args) 
	{
		//起始时间
		long start =System.currentTimeMillis();
		//复制MP3文件
		copyMedia();
		//终止时间
		long end =System.currentTimeMillis();
		System.out.println(end-start+"ms");
	}
	public static void copyMedia(){
		BufferedInputStream bufi=null;
		BufferedOutputStream bufo=null;
		try{
			//定义读取和写入缓冲区
			bufi=new BufferedInputStream(new FileInputStream("1.mp3"));
			bufo=new BufferedOutputStream(new FileOutputStream("1copy.mp3"));
			int by=0;
			while((by=bufi.read())!=-1){
				bufo.write(by);
			}
		}
		catch(Exception e){
			throw new RuntimeException("读写失败");
		}
		finally{
			try{
				if(bufi!=null)
					bufi.close();
			}
			catch(Exception e){
				throw new RuntimeException("关闭读取失败");
			}
			try{
				if(bufo!=null)
					bufo.close();
			}
			catch(Exception e){
				throw new RuntimeException("关闭写入失败");
			}
		}
	}
}
复制MP3音频文件(方式二)
/*
 MP3复制(方式二)
 自定义缓冲区

*/
import java.io.*;
class  mp3Copy2
{
	public static void main(String[] args) throws IOException
	{
		long start=System.currentTimeMillis();
		copyMedia();
		long end=System.currentTimeMillis();
		System.out.println(end-start+"ms");
	}
	public static void copyMedia(){
		MyBufferedInputStream bufi=null;
		BufferedOutputStream bufo=null;
		try{
			//定义读取和写入缓冲区
			bufi=new MyBufferedInputStream(new FileInputStream("1.mp3"));
			bufo=new BufferedOutputStream(new FileOutputStream("3copy.mp3"));
			int by=0;
			while((by=bufi.myRead())!=-1){
				//通过myRead方法将byte提升了int型,而write方法则又
				//将int型转化为byte型,只截取了int型的低8位。
				//write返回的是byte
				bufo.write(by);
			}
		}
		catch(Exception e){
			throw new RuntimeException("读写失败");
		}
		finally{
			try{
				if(bufi!=null)
					bufi.myClose();
			}
			catch(Exception e){
				throw new RuntimeException("关闭读取失败");
			}
			try{
				if(bufo!=null)
					bufo.close();
			}
			catch(Exception e){
				throw new RuntimeException("关闭写入失败");
			}
		}
	}
}
class MyBufferedInputStream
{
	private InputStream in;
	private int count=0,pos=0;
	private byte[] buf=new byte[1024];
	MyBufferedInputStream(InputStream in){
		this.in=in;
	}
	//一次读取一个字节,从缓冲区获取。
	public int myRead()throws IOException{
		//count为0表示buf中么有数据了。
		if(count==0){
			//从缓冲区中抓去一批数据存储到buf中,in.read(buf)返回获取到
			//的字节个数,并将获取到的数据存储到buf中
			count=in.read(buf);
			//倘若count小于0,则没有读取到数据。
			if(count<0){
				return -1;
			}
			//获取到数据后,pos指向数组的0位置。
			pos=0;
			//从数组中获取一个字节的数据并返回
			byte b=buf[pos];
			count--;
			pos++;
			//由于myRead()函数返回的是int型,而b为byte型,相当于向上提升。
			//音频文件中可能出现连续的1111 1111,而此时不是文件结束的标志,
			//只有当count<0返回-1时才表示读取到文件末尾。
			//若b为1111 1111,返回int时在原值前面补了1,为11111111 11111111 11111111 11111111
			//若在前面补0,则可以避免-1的出现。
			return b&0xff;
		}
		else if(count>0){
			byte b=buf[pos];
			count--;
			pos++;
			return b&0xff;
		}
		return -1;
		
	}
	public void myClose()throws IOException{
		in.close();
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值