1.1 字符流的缓冲区
缓冲区的出现提高了对数据的读写效率
对应类:
BUfferWriter
BufferedReader
特点:缓冲区要结合流才可以使用,在创建缓冲区之前,必须要有流对象。在流的基础上对流的功能进行了增强。
BUfferWriter步骤:
1.创建一个字符写入流对象
FileWriter fw=new FileWriter("a.txt");
2.将需要被提高效率的流对象作为参数传递给缓冲区的构造函数
bufferedWriter bufw=new BufferedWriter(fw);
buff.write("asdasdas");
bufw.newLine();//换行符,跨平台的
3.将缓冲区刷新
bufw.flush;
4.关闭缓冲区,就是在关闭缓冲区中的流对象
bufw.close();
BufferedReader步骤
1.创建一个字符写入流对象
FileReader fr=new FileReader ("a.txt");
2.将需要被提高效率的流对象作为参数传递给缓冲区的构造函数
BufferedReader bufr=new BufferedReader (fr);
3.读取流对象:该缓冲区提供了一个一次读取一行的方法。当返回null时表示,文件读到末尾
String line=null;
while((line=bufr.readLine())!=null)
{
String s=line;}
4.关闭
bufr.close();
readLine()方法的原理:
无论是读一行,获取多个字符,最终都是在硬盘上一个一个读取,最终使用额还是read方法一次读一个的方法。
缓冲区练习:通过缓冲区复制一个文件(示例1)
1 示例1 2 BufferWriter bufw=null; 3 BufferReader bufr=null; 4 try { 5 bufw=new BufferWriter(new FileWriter("b.txt")); 6 bufr=new BufferReader(new FileReader("a.txt")); 7 String line=null; 8 while ((line=buffr.read(buf))!=null){ 9 bufw.write(line); 10 bufw.newLine(); 11 bufw.flsuh; 12 } 13 } 14 catch (IOException e) { 15 // TODO Auto-generated catch block 16 e.printStackTrace(); 17 } 18 finally 19 { 20 try { 21 fr.close(); 22 } catch (IOException e) { 23 24 e.printStackTrace(); 25 } 26 27 try { 28 fw.close(); 29 } catch (IOException e) { 30 31 e.printStackTrace(); 32 } 33 }
1.2 装饰设计模式
当想要对已有的独享进行功能增强时,可以定义类,将已有的对象传入,基于已经有的功能,
并提供加强功能,那么自定义的该类称为装饰类
装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。
代码演示(示例2):
1 示例2: 2 3 已知类: 4 Person() 5 { 6 public void chifan() 7 { 8 } 9 } 10 增强类: 11 superPerson() 12 { 13 private Person p; 14 superPerson(Person p) 15 { 16 this.p=p; 17 } 18 19 public void superchifan() 20 { 21 p.chifan(); 22 ......... 23 { 24 }
1.2.1 装饰和继承都能实现一样的特点:进行功能的扩展增强。有什么区别呢?
以前是通过继承将每一个子类都具备缓冲功能。
那么继承体系会复杂,并不利于扩展。
现在优化思想。单独描述一下缓冲内容。
将需要被缓冲的对象。传递进来。也就是,谁需要被缓冲,谁就作为参数传递给缓冲区。
这样继承体系就变得很简单。优化了体系结构。
装饰模式比继承要灵活。避免了继承体系臃肿。
而且降低了类于类之间的关系。
装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。
所以装饰类和被装饰类通常是都属于一个体系中的。
1.3 LineNumberReader 带有行号的缓冲区:
LineNumberReader lnr=new LineNumberReader();
获取行号:lnr.getLineNumber();
设置行号从几开始:lnr.setLineNumber(100);
LineNumberReader 步骤
1.创建一个字符写入流对象
FileReader fr=new FileReader ("a.txt");
2.将需要被提高效率的流对象作为参数传递给缓冲区的构造函数
LineNumberReader lnfr=new LineNumberReader (fr);
3.读取流对象:该缓冲区提供了一个一次读取一行的方法。当返回null时表示,文件读到末尾
String line=null;
while((line=lnfr.readLine())!=null)
{
String s=line;
String linenum=lnfr.getLineNumber();
}
4.关闭
lnfr.close();
1.3.1 自定义带行号的MyLineNumber(示例3):
1 示例3: 2 public class MyLineBufferReader extends MyBufferedReader { 3 4 public MyLineBufferReader(Reader r) { 5 super(r); 6 7 } 8 9 private int LineNumber; 10 11 public int getLineNumber() { 12 return LineNumber; 13 } 14 15 public void setLineNumber(int lineNumber) { 16 LineNumber = lineNumber; 17 } 18 19 public String myReadLine() throws IOException 20 { 21 LineNumber++; 22 return super.myReadLine(); 23 } 24 25 }
1.4 IO流常用基类-字节流InputStream OutputStream
基本操作与字符流类相同。但它不仅可以操作字符,还可以操作其他媒体文件。
1.4.1 需求:复制一个图片。
想要操作图片数据。这时就要用到字节流(示例4):
思路:
1,用字节读取流对象和图片关联。
2,用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。
3,通过循环读写,完成数据的存储。
4,关闭资源。
1 示例4: 2 import java.io.*; 3 class CopyPic 4 { 5 public static void main(String[] args) 6 { 7 FileOutputStream fos = null; 8 FileInputStream fis = null; 9 try 10 { 11 fos = new FileOutputStream("c:\\2.bmp"); 12 fis = new FileInputStream("c:\\1.bmp");//源 13 14 byte[] buf = new byte[1024]; 15 16 int len = 0; 17 18 while((len=fis.read(buf))!=-1)//只要不等于-1的话就往里边写 19 { 20 fos.write(buf,0,len); 21 } 22 } 23 catch (IOException e) 24 { 25 throw new RuntimeException("复制文件失败"); 26 } 27 finally 28 { 29 try 30 { 31 if(fis!=null) 32 fis.close(); 33 } 34 catch (IOException e) 35 { 36 throw new RuntimeException("读取关闭失败"); 37 } 38 try 39 { 40 if(fos!=null) 41 fos.close(); 42 } 43 catch (IOException e) 44 { 45 throw new RuntimeException("写入关闭失败"); 46 } 47 } 48 } 49 }
1.5 字节流的缓冲区:同样是提高了字节流的读写效率
BufferedOutputStream
BufferedInputStream
示例5:通过缓冲区演示对mp3的复制
1 示例5: 2 import java.io.*; 3 class CopyMp3 4 { 5 public static void main(String[] args) throws IOException 6 { 7 long start = System.currentTimeMillis(); 8 copy_2(); 9 long end = System.currentTimeMillis(); 10 11 System.out.println((end-start)+"毫秒"); 12 } 13 14 public static void copy_2()throws IOException 15 { 16 MyBufferedInputStream bufis = new MyBufferedInputStream(new FileInputStream("c:\\9.mp3")); 17 BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("c:\\3.mp3")); 18 19 int by = 0; 20 21 //System.out.println("第一个字节:"+bufis.myRead()); 22 23 while((by=bufis.myRead())!=-1) 24 { 25 bufos.write(by); 26 } 27 28 bufos.close(); 29 bufis.myClose(); 30 } 31 32 //通过字节流的缓冲区完成复制。 33 public static void copy_1()throws IOException 34 { 35 BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("c:\\0.mp3")); 36 BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("c:\\1.mp3")); 37 38 int by = 0; 39 40 while((by=bufis.read())!=-1) 41 { 42 bufos.write(by); 43 } 44 45 bufos.close(); 46 bufis.close(); 47 48 49 } 50 }