首页 > 代码库 > 黑马程序员_IO流1

黑马程序员_IO流1

 

                              异常
1、异常的继承体系:
  java.lang.Throwable类,所有异常和错误的父类
  Error类所有错误的父类
  Exception类所有异常的父类
    RuntimeException
    NullPointerException
    ClassCastException
    IndexOutOfBoundsException
  错误,比较严重的问题,一旦出现了错误,程序根本不能运行,必须修改源代码。
  异常,比较轻微的问题,一旦出现了异常,程序可以处理掉异常,继续运行。异常一般是程序的最后一个问题。

2、Throwable类
  构造方法 Throwable(String message)异常信息
  String getMessage()返回异常信息的详细字符串
  String toString()返回异常信息的简短描述
  void printStackTrace()将异常信息直接输出在控制台
3、异常的第一种处理方式
  try catch 代码块处理
  标准格式:
    try{
      被检测的代码,可能出现异常的代码
    }catch(异常类 变量){
       异常的处理方式
      变量.调用Throwable类的三个方法
    }
4、异常的第二种处理方式抛出异常
    如果程序运行的时候,由于用户或者调用非法传递参数,导致程序出现问题,假如调用者真的传递了非法的数据,需要手动抛出异常。在方法中,使用关键字throw 写异常对象,new 出来    的.如果一直一层层的往外抛异常,直到抛给JVM。这样真的发生了问题,程序就会停止运行。所以不建议一直往外抛。
5、throw 和throws的区别:
    throw 写在方法内部,后面必须希望new 异常();
    throws 写在方法的声明上,后面必须写异常类名。
6、编译时期异常和运行时期异常
  编译时期异常:调用了一个抛出异常的方法,不处理,编译失败
  运行时期异常:RuntimeException类和他所有的子类都属于运行时期异常
  特点:如果方法内部用throw 抛出的是一个运行时期异常,此时方法声明上,不需要使用throws声明异常,调用者不需要处理这个异常,Java工程师们设计运行时异常的初衷,运行时期异常一     旦发生,程序必须停下来修改源代码。
7、自定义的异常
  Java原有异常体系中,很多的现象进行异常的封装,越界,类型转换,JDK中也有想不到的异常,所以自定义异常
    第一步,入伙 。继承 Exception 或者继承RuntimeException
    第二步,传递异常信息,将异常信息传递给Exception的构造方法
  注意:异常必须是Exception或者RuntimeException的子类

class MyException extends RuntimeException{	MyException(String message){	   super(message);	}}

  

8、finally代码块

    try{} catch(Exception e){} finally{}

    try{} finally{}

    finally代码块中的程序,必须要执行,不管程序有没有异常方法,finally中的程序必须执行

 注:finally代码块中不能放返回值语句,否则前面的都没有意义。

 finally的用处:

     用于释放资源

9、子类继承父类后的异常细节:

    父类不抛,子类不能抛;

    父类抛了,子类可抛可不抛;子类如果抛了,那么异常的类型不能超过父类;

    方法中可以抛多个异常,但如果抛出的是编译时期的异常,需要声明,而且调用者要写多个catch处理;

    多catch处理中,最高异常放最后面。但一般不使用带子父类关系的异常。

 

 

                                          IO流

1、IO中的继承体系

    字符输出流,写文本文件的,抽象基类 java.io.Writer,写文件的,写的方法有:

      write(字符数组)  write(字符数组一部分) write(单个字符) write(字符串)

     字符输入流,读文本文件的,抽象基类 java.io.Reader,读文件的,读的方法有

      read()单个字符  read(字符数组)  read(字符数组一部分)

    字节输出流,写任意文件的,抽象基类 java.io.OutputStream,写文件的,写的方法

      write(单个字节)  write(字节数组) write(字节数组一部分)

     字节输入流,读任意文件的,抽象基类 java,io.InputStream,读文件的,读的方法

      read()单个字节  read(字节数组)  read(字节数组一部分)

  

 

                                      字符流

1、字符输出流写文本文件

    字符输出流 父类Writer不能直接使用,所以找子类FileWriter

      构造方法 FileWriter(字符串的文件名) 

    字符流在写数据的时候,write方法写,数据写在了内存中,并没有直接写到目的文件中。如果让数据写到目的文件中,字符流要进行缓存区的刷新操作。Writer中的方法flush,刷新流的缓     冲,将数据写到目的地。 

    文件的续写,文件的后面追加写入,原有的数据都被保留下来

      FileWriter类构造方法中,传递String的文件名,true实现追加写入

2、字符输入流读文本文件

    Reader类是抽象类,找子类FileReader

      构造方法  FileReader(字符串文件名)

     FileReader调用父类方法实现读取功能

     A.读取单个字符的方法

        int read() 读取一个字符

       read()方法,每次只能读取一个字符,返回这个字符的码值,每调用一次read()自动向后读取一个字符,如果读取到文件的末尾,返回-1。

     注意:文件读取的时候,一次循环不允许出现2read()

          保证读取的文件必须是GBK编码的(ANSI)   

    B.读取字符数组 int read(char[] ch),每次读取到的字符,装在字符数组中,返回每次读取的有效字符个数

3、字符输出流的缓冲区对象

    数组的缓冲,提高了流对象的读写效率,开发出现流对象的缓冲区对象,目的提高流的操作效率。字符输出流的缓冲区 java.io.BufferedWriter   

    字符输出流缓冲区对象方法:   

      构造方法 BufferedWriter(Writer out)传递的是Writer的子类对象

 

      void newLine()写一个换行。此方法具有跨平台性,\r\n Windows下有效,Linux操作系统\n 

4、字符输入流的缓冲区对象 java.io.BufferedReader

    字符输入流缓冲区对象的方法

      构造方法 BufferedReader(Reader in),传递是的Reader类的子类对象

 

      String readLine()读取文本一行,返回字符串,读取文件结尾,返回null,读取一行,返回的字符串中,没有\r\n符号,返回是一行有效字符

5、用字符流复制文本的三种方式:

    A、字符流对象完成,读一个,写一个

 

 

 

 

 

 

 1 package cn.itcast.iostream; 2 /* 3  * 复制文本文件:字符流对象完成,读一个字符,写一个字符 4  * 实现步骤: 5  *   1. FileReader建立对象,包装源文件 c:\a.html 6  *   2. FileWriter建立对象,包装目的文件 d:\a.html 7  *   3. read方法读取一个字符 8  *   4. write方法写一个字符,刷新 9  *   5. 关闭资源10  */11 import java.io.*;12 public class CopyText {13     public static void main(String[] args) {14         //建立两个流对象15         FileReader fr = null;16         FileWriter fw = null;17         try{18             fw = new FileWriter("d:\\w.log");//数据目的19             fr = new FileReader("c:\\w.log");//数据源20             //开始循环读取源文件,读一个字符写一个字符21             int len = 0 ;22             while((len = fr.read())!=-1){23                 fw.write(len);24                 fw.flush();25             }26         }catch(IOException e){27             //输出异常信息28             e.printStackTrace();29             throw new RuntimeException("复制失败");30         }finally{31             try{32                 if(fr!=null)33                     fr.close();34             }catch(IOException e){35                 throw new RuntimeException("读取源关闭失败");36             }finally{37                 try{38                     if(fw!=null)39                         fw.close();40                 }catch(IOException e){41                     throw new RuntimeException("文件写入关闭失败");42                 }43             }44         }45     }46 }

    B.读取字符数组 int read(char[] ch),每次读取到的字符,装在字符数组中,返回每次读取的有效字符个数

    

1          char[] buf = new char[1024];2             int len = 0 ;3             while((len = fr.read(buf))!=-1){4                 fw.write(buf,0,len);5                 fw.flush();6             }

    C.利用字符流的缓冲区对象。增加了读取行的功能。读一行写一行

     

    bfr = new BufferedReader(new FileReader("c:\\c.txt"));
    bfw = new BufferedWriter(new FileWriter("d:\\c.txt"));
    String line = null;
    // 循环读取文件,行读和写
    while((line = bfr.readLine())!= null){
      bfw.write(line);
      bfw.newLine();
      bfw.flush();
    }

 

                                  字节流

1、字节输出流

     字节可以操作任意文件,字节输出流,写任意文件,单个字节8个二进制。  不查询编码表。

     字节输出流的抽象基类OutputStream

     写的方法:写字节数组,字节数组一部分,单个字节

     子类FileOutputStream类,文件的输出

     字节流写数据,不需要刷新,直接向数据写到目的地

2、字节输入流

    字节可以操作任意文件,字节输入流读取文件,单个字节8个二进制

    字节输入流的抽象基类InputStream

    读取的方法:读取单个字节,读取字节数组,读取字节数组一部分

    子类是FileInputStream,构造方法直接传递字符串文件名

    读取单个字节的read()方法,返回字节的码值,文件末尾返回-1

    int available()返回字节输入流封装的文件的字节数

3、字节流复制文件的方法:和字符流的复制方法相似

    第一种方式读取一个字节,写一个字节

 

    第二种方式读取一个字节数组,写一个字节数组--重点案例,必须要写熟练

    

import java.io.*;public class CopyFile2 {    public static void main(String[] args) {        long start = System.currentTimeMillis();        FileInputStream fis = null;        FileOutputStream fos = null;        try{            fis = new FileInputStream("c:\\1.avi");            fos = new FileOutputStream("d:\\1.avi");            int len = 0 ;            byte[] bytes = new byte[1024];            while((len = fis.read(bytes))!=-1){                fos.write(bytes,0,len);            }        }catch(IOException e){            e.printStackTrace();            throw new RuntimeException("复制失败");        }finally{            try{                if(fos!=null)                    fos.close();            }catch(IOException e){                throw new RuntimeException("文件写入关闭失败");            }finally{                try{                    if(fis!=null)                        fis.close();                }catch(IOException e){                    throw new RuntimeException("文件读取关闭失败");                }            }        }        long end = System.currentTimeMillis();        System.out.println(end - start);    }}

 

 

 

     第三种方式读取文件,用字节流缓冲区实现

  注:所有的read方法readLine方法,等待效果,线程阻塞.

                                            转换流

1、 InputStreamReader

   System类的静态成员变量 public static final InputStream in;返回的字节输入流对象,这个对象是JVM底层自带的一个字节输入流,它的父类是InputStream.

   InputStreamReader是Reader的子类,字符流对象,字节流向字符的桥梁。InputStreamReader有一个子类就是FileReader

 

 

   InputStreamReader构造方法:InputStreamReader(InputStream in)传递字节输入流,变成字符流

2、OutputStreamWriter

  System类的静态成员变量 public static final PrintStream out;返回打印流对象PrintStream,也是OutputStream的子类

 

  OutputStreamWriter是Writer的子类,字符流对象,字符流向字节的桥梁

 

  OutputStreamWriter构造方法,OutputStreamWriter(OutputStream out)传递的是字节输出流

3、转换流的案例

  

/**从键盘输入,转为大写,再从控制台输出*/    public static void main(String[] a) throws IOException {        BufferedReader bfr = new                 BufferedReader(new InputStreamReader(System.in));        BufferedWriter bfw = new                 BufferedWriter(new OutputStreamWriter(System.out));                String line = null;        while ((line = bfr.readLine()) != null) {            if ("over".equals(line))                break;            bfw.write(line.toUpperCase());            bfw.newLine();            bfw.flush();        }        bfw.close();        bfr.close();    }

 

 

 

 

  注:转换流只能用来操作文本文件。因为InputStreamReader和OutputStreamWriter都是字符流。

    他们传递的参数都是字节流,但是他们的流向不同,一个输出,一个输入。

 

 

 

                                    编码表

 

1、常见的编码表:

       每一个字符,在编码中,对应一个十进制数,十进制转为二进制就能被计算机 识别了。

       ASCII 美国标准信息交换码      内面只有 符号,数字,字母(大小写区别)的编码

       GBK,在ASCII基础上加入了汉字,汉字对应二个十进制数

       Unicode 万国码

         现在使用的UTF-8中,汉字是三个字节

       ISO8859-1 拉丁文。

2、在转换流对象中,可以指定编码表

   转换流对象,构造方法,第一个参数是字节流,第二个参数可写编码表的名字

  注:若编码表为GBk,可以不写。

3、乱码和???

   ??? 不是乱码,编码表中,没有查到任何数据

   獾才编码表中查到的结果

 注:以后做程序,如果发生乱码或者???现象,是由于采用的编码表不一致造成的

 4、字符的编码和解码

    将一个字符串转成字节数组,称为字符的编码 String类的方法getBytes

   getBytes()还有一个重载函数:byte[] getBytes(编码表)

    将字节数组还原会字符串,成为字符的解码   String类的构造方法

    String同样有一个重载构造函数String(byte[] bytes ,编码表)

 

 1 public class CharEncoding { 2     public static void main(String[] args)throws Exception { 3         //method(); 4         //method_1(); 5         byte[] bytes= "琲".getBytes(); 6         for(byte b : bytes){ 7             System.out.println(b); 8         } 9     }10     //将字符串你好,转成字节数组,查询UTF-811     public static void method_1() throws Exception{12         byte[] bytes = "你好".getBytes("utf-8");13         for(byte b : bytes){14             System.out.println(b);15         }16         byte[] bytes2 = {-28,-67,-96,-27,-91,-67};17         System.out.println(new String(bytes2,"utf-8"));18     }19     20     //将字符串,你好,转成字节数组21     public static void method(){22         byte[] bytes = "你好".getBytes();23         //将你好两个字,进行编码表的查询GBK,将汉字对应的十进制数,存储到字节数组24         for(byte b : bytes){25             System.out.println(b);26         }27         28         byte[] bytes2 = {-60,-29,-70,-61};29         String s = new String(bytes2);30         System.out.println(s);31     }32 }