第一讲 IO概述
1概述:IO流:输入(Input与Output流)
2特点:
a、IO流用于数据传输; b、按操作分为字节流与字符流 c、按流向分:输入流和输出流
3、常用IO流的基类
1)字节流的基类:InputStream和OutpuStream
2)字符流的基类:Reader和Writer
第二讲 字符流
一、简述
1、字符流的对象融合了编码表。使用的是默认的编码
2、字符流只能用于文字处理,而字节流可以处理其他:
3、下列把FileWriter和FileReader一起讲
1 package System;
2 /* 3 * 将文件做复制 4 */ 5 import java.io.*; 6 public class CopyTest { 7 public static void main(String[] args){ 8 int s1=(int) System.currentTimeMillis(); 9 copy_1(); 10 int s2=(int) System.currentTimeMillis(); 11 copy_2(); 12 int s3=(int) System.currentTimeMillis(); 13 System.out.println(s2-s1+"毫秒");//顺便计算下时间 14 System.out.println(s3-s2+"毫秒"); //顺便计算下时间 15 } 16 17 private static void copy_1() { 18 FileWriter fw=null; 19 FileReader fr=null; 20 try { 21 fw=new FileWriter("xxx_1.txt");//创建输入的文件xxx_1 22 fr=new FileReader("TestDemo.java"); //创建要输出的流 23 for(int ch=0;(ch=fr.read())!=-1;){//一个字节一个自己读并输出 24 fw.write((char)ch); 25 } 26 } catch (IOException e) { 27 throw new RuntimeException("毒性"); 28 }finally{ 29 if(fr!=null) 30 try { 31 fr.close(); 32 } catch (Exception e2) { 33 // TODO: handle exception 34 } 35 if(fw!=null) 36 try { 37 fw.close(); 38 } catch (Exception e2) { 39 // TODO: handle exception 40 } 41 } 42 43 } 44 45 private static void copy_2() { 46 FileWriter fw=null; 47 FileReader fr=null; 48 try { 49 fw=new FileWriter("xxx_2.txt"); 50 fr=new FileReader("TestDemo.java"); 51 char[] buff=new char[1024];//第二种方法是字符数组的形式读取并输出,一般创建1024整数倍的数组 52 for(int len=0;(len=fr.read(buff))!=-1;){//fr.read(buff)指定是中buff的长度 53 fw.write(new String(buff,0,len));//记住这里新创了个String把读出来的buff从0到len 54 } 55 } catch (IOException e) { 56 throw new RuntimeException("毒性"); 57 }finally{ 58 if(fr!=null) 59 try { 60 fr.close(); 61 } catch (Exception e2) { 62 // TODO: handle exception 63 } 64 if(fw!=null) 65 try { 66 fw.close(); 67 } catch (Exception e2) { 68 // TODO: handle exception 69 } 70 71 } 72 } 73
字符缓冲流:
1、缓冲流的出现为了提高读写效率,所以在缓冲区创建钱就先创建对象。
使用复制一个java文件说明使用方法:
import java.io.*; //使用缓冲流的方法复制文件来学习使用的格式 public class BuferedTest { public static void main(String[] args){ BufferedWriter bufw=null; BufferedReader bufr=null; try { bufw=new BufferedWriter(new FileWriter("xx.txt"));//无法添加ture bufr=new BufferedReader(new FileReader("TestDemo.java")); String line=null; while(!((line=bufr.readLine())==null)){ bufw.write(line); bufw.newLine();//记得换行 bufw.flush(); } } catch (IOException e) { throw new RuntimeException("书写错误"); }finally{ try { if(bufr!=null) bufr.close(); } catch (IOException e) { throw new RuntimeException("读取错误"); } try { if(bufw!=null) bufw.close(); } catch (IOException e) { throw new RuntimeException("读取错误"); } } } }
3、自定义BufferedReader
原理:
可根据BufferedReader类中特有一行一行读取原理,分析思路如下
思路:
1:它的构造函数中参数是FileReader,所以一创建就有FileReader;
2、在执行ReadLine时,先需要一个容器(StringBuilder)容纳一行的数据,和int容纳一个字节数据
然后只在出现、n是返回
3、最后关闭的是close()的动作就是关闭里面的FileReader;
装饰设计模式:
简述:
当想要对已有的对象进行功能增强时,可以定义类,将有已有对象作为构造函数的参数传入,基于已有对象的功能进行加强,那么自定义的该类称之装饰类
我们上面的MyBufferedReader就装饰设计模式的好例子。
为什么使用装饰而不是继承来增加功能?
a、装饰模式避免了继承体现的臃肿
b、装饰类因为是增强已有对象,所以必然需要与已有对象相同的功能,所以装饰类和被装饰类是同一个体现
c、增加者与被增强者的继承结构转为组合结构
1 /* 2 自定义BufferedReader 3 原理: 4 可根据BufferedReader类中特有一行一行读取原理,分析思路如下 5 思路: 6 1:它的构造函数中参数是FileReader,所以一创建就有FileReader; 7 8 2、在执行ReadLine时,先需要一个容器(StringBuilder)容纳一行的数据,和int容纳一个字节数据 9 10 然后只在出现、n是返回 11 3、最后关闭的是close()的动作就是关闭里面的FileReader; 12 */ 13 import java.io.*; 14 15 import javax.management.RuntimeErrorException; 16 class MyBufferedReader extends Reader{ 17 private Reader fr;//等于一创建就有这个fr的FileReader 18 MyBufferedReader(Reader fr){//从FileReader(子类)变Reader(父类),多态增加使用范围 19 this.fr=fr; 20 } 21 22 // 一下是自定义的读取一行的方法myReadLine 23 public String myReadLine() throws IOException{ 24 // 一个容器StringBuilder和字节容器int 25 StringBuilder sb=new StringBuilder(); 26 int ch=0; 27 while((ch=fr.read())!=-1){//返回负一时就跳出循环 28 if(ch==‘\r‘)//如果换行符,则继续 29 continue; 30 if(ch==‘\n‘)//如果回车符 31 return sb.toString(); 32 else 33 sb.append((char)ch); 34 } 35 if(sb.length()!=0) 36 return sb.toString(); 37 return null; 38 } 39 // 父类中的close也是抽象方法 40 public void close()throws IOException{//实际上就是关闭FileReader 41 fr.close(); 42 } 43 44 // 复写父类Reader中的抽象方法 45 public int read(char[] cbuf, int off, int len) throws IOException { 46 return fr.read(cbuf,off,len); 47 } 48 } 49 public class MyBufferedReaderDemo { 50 public static void main(String[] args){ 51 //使用方法和原方法一样 52 MyBufferedReader mbr=null; 53 try { 54 mbr=new MyBufferedReader(new FileReader("TestDemo.java")); 55 String line=null; 56 while((line=mbr.myReadLine())!=null){//一行的数据已经给了line 57 System.out.println(line); 58 } 59 } catch (IOException e) { 60 throw new RuntimeException("数据读取失败"); 61 } 62 finally{ 63 try { 64 if(mbr!=null) 65 mbr.close(); 66 } catch (IOException e2) { 67 throw new RuntimeException("关闭流失败"); 68 } 69 } 70 71 } 72 }
练习:带行数的缓冲流,LineNumber的运用
1 import java.io.*; 2 3 import javax.management.RuntimeErrorException; 4 public class LinewNumberReaderDemo { 5 public static void main(String[] args) { 6 FileReader fr=null; 7 LineNumberReader lnr=null;//可以带行数的缓冲流 8 try { 9 fr=new FileReader("TestDemo.java"); 10 lnr=new LineNumberReader(fr); 11 12 String line=null; 13 lnr.setLineNumber(50);//设置从50开始数 14 15 while((line=lnr.readLine())!=null){ 16 System.out.println(lnr.getLineNumber()+":"+line);//getLineNumber就是 17 //得到行数 18 } 19 } catch (IOException e) { 20 throw new RuntimeException("数据输入有误"); 21 } 22 finally{ 23 try { 24 if(lnr!=null) 25 lnr.close(); 26 } catch (Exception e2) { 27 } 28 } 29 } 30 }