Java异常处理与输入输出.ppt
第六章 Java异常处理、IO,李莉,1.Java异常处理 2.Java输入输出,public class Temp public static void main(String args)String a=Hello,Java,World,!;for(int i=0;i5;i+)System.out.println(ai);,1.异常处理,异常(Exception):是特殊的运行错误对象,对应着Java语言特定的运行错误处理机制。通常Java程序运行在网络环境中,需要考虑安全性。为了处理程序中的运行错误,Java中引入了异常和异常类。与其他对象一样,异常是面向对象的一部分,是异常类的对象。,1.异常处理,Java中定义了很多异常类,每个异常类代表了一种运行错误,类中包含了该运行错误的信息和处理错误的方法等内容。当Java程序运行过程中发生运行错误时,如果该运行错误是程序中已经定义过、可以被识别的错误,系统就会自动产生一个相应的异常类的对象,即产生一个异常。一旦产生了一个异常对象,系统中就一定有相应的机制来处理它,确保不会产生死机、死循环或其他对操作系统的损害,保证整个程序运行的安全性Java的异常处理机制。,1.异常处理,异常类结构与组成:Java的异常类是处理运行时错误的特殊类,每一种异常类对应一种特定的运行错误。所有的Java异常类都是Exception类的子类。,1.异常处理Throwable类,1.异常处理,Throwable类:在java.lang包中的类;Throwable类派生了两个子类:Exception和Error;Error类由系统保留;Exception类则提供给应用程序使用。,1.异常处理Exception类,Exception类:Exception(String message):创建一个新的异常,message通常为该异常所对应的错误的描述。,1.异常处理Exception类,public String toString():返回描述当前Exception类信息的字符串。public void printStackTrace():在标准输出设备上输出当前异常对象的堆栈使用情况,也即程序先后调用执行了哪些对象或类的哪些方法,使运行过程中产生了这个异常。,1.异常处理系统定义的异常类,Exception类有若干子类,每一个子类代表了一种特定的运行时错误。这些子类有些是系统事先定义好并包含在Java类库中的,称为系统定义的异常类。系统定义的运行异常通常对应着系统运行错误。这些错误可能导致操作系统错误甚至是整个系统的瘫痪,所以定义异常类进行处理。,1.异常处理系统定义的异常类,由于定义了运行时错误所相应的异常,Java程序即使产生一些致命的错误(如引用空对象等),系统也会自动产生一个对应的异常对象来处理这个错误,避免其蔓延或产生更大的问题。,1.异常处理用户定义的异常类,系统定义的异常主要用来处理系统可以预见的较常见的运行错误;对于某个应用所特有的运行错误,需要程序员根据程序的特殊情况在程序中定义自己的异常类和异常对象。用户自定义异常主要用来处理用户程序中特定的逻辑运行错误。,1.异常处理用户定义的异常类,例:队列Queue中,出队列方法dequeue(),int dequeue()/出队列操作,若队列不空,则从队列头部取出一个数据int data;if(!isEmpty()data=m_FirstNode.getData();m_FirstNode=m_FirstNode.getNext();return data;else return-1;/调用此方法的方法需要单独处理;队列中不能保存“-1”,1.异常处理用户定义的异常类,定义异常类EmptyQueueException,专门处理“从空队列中出队”的逻辑错误:,class EmptyQueueException extends Exception/用户自定义的系统类的子类Queue sourceQueue;public EmptyQueueException(Queue q)super(“队列已空。”);sourceQueue=q;public String toString()/重载父类的方法,给出详细的错误信息 return(“队列”+sourceQueue.toString()+”为空,执行出队操作引发异常”);,1.异常处理用户定义的异常类,用户自定义异常处理程序中可能产生的逻辑错误,使这种错误能够及时地被系统识别、处理,不致扩散产生更坏的影响,从而使程序有更好的容错性、更安全稳定。创建用户自定义异常:(1)声明一个新的异常类,以Exception类或其他系统异常类或用户异常类为父类;(2)为新的异常类定义属性和方法,或重载父类的属性和方法,使这些属性和方法能够体现所对应错误的信息。,1.异常处理抛出异常,Java程序在运行时,如果发生了一个可识别的错误,系统就会产生一个与该错误相对应的异常类的对象,这个过程称为抛出异常。,1.异常处理抛出异常,(1)系统定义的运行异常系统自动抛出所有系统定义的运行异常都可由系统自动抛出。,public class Temp public static void main(String args)int a=0,b=5;System.out.println(b/a);/以零为除数,引发系统定义的算术异常,1.异常处理抛出异常,(2)自定义的异常语句抛出用户自定义的异常必须借助于throw语句来抛出,说明哪种情况产生了这种错误,并抛出该异常类的新对象。用throw语句抛出异常对象的语法格式为:,修饰符 返回类型 方法名(参数列表)throws 异常类名列表throw 异常类名;,1.异常处理抛出异常,使用throw语句抛出异常:(1)通常在一定条件下才会抛出异常,应把throw语句放在if语句中,只有当if条件满足、用户定义的逻辑错误发生时才执行。(2)含有throw语句的方法,应该在方法头中增加如下部分:throws 异常类名列表告知所有调用者该方法包含throw语句,要准备接受和处理在运行过程中可能会抛出的异常。如果方法中的throw语句不止一个,方法头的异常类名列表也不止一个,应该包含所有可能产生的异常。,class EmptyQueueException extends Exception/用户自定义的系统类的子类Queue sourceQueue;public EmptyQueueException(Queue q)super(“队列已空。”);sourceQueue=q;public String toString()/重载父类的方法,给出详细的错误信息 return(“队列”+sourceQueue.toString()+”为空,执行出队操作引发异常”;,int dequeue()throws EmptyQueueException/出队列操作,若队列不空,则从队列头部取出一个数据int data;if(!isEmpty()data=m_FirstNode.getData();m_FirstNode=m_FirstNode.getNext();return data;else throw(new EmptyQueueException(this);,用户自定义的异常,需要程序员在程序的合适位置创建自定义异常的对象,并利用throw语句将这个异常对象抛出,1.异常处理处理异常,(1)捕捉异常:一个异常被抛出时,应该有专门的语句来接收被抛出的异常对象,称为捕捉异常。当一个异常类的对象被捕捉后,用户程序就会发生流程的跳转,系统中止当前的流程而跳转至专门的异常处理语句块,或直接跳出当前程序和Java虚拟机回到操作系统。,1.异常处理处理异常,在Java中,异常对象是被catch语句捕捉和处理的。异常处理语句块的格式如下:catch(异常类名 异常形式参数名)异常处理语句组;,1.异常处理处理异常,每个catch语句块都应该与一个try语句块相对应。try语句块用来对其中的语句进行监视,出现异常的时候启动Java的异常处理机制。可能抛出异常的语句(包括throw语句、调用可能抛出异常的方法的方法调用语句),都应该包含在try语句块中。,public class Temp public static void main(String args)int a,b;tryb=0;a=3/b;catch(ArithmeticException e)System.out.println(Exception:);e.printStackTrace();System.out.println(OK,Its Here!);,1.异常处理处理异常,(2)多异常的处理:一个try块可能产生多种不同的异常,可以使用多异常处理机制,用多个catch语句块对所有可能的异常进行捕获,每个catch块用来接收和处理一种特定的异常对象。如:public T newInstance()throws nstantiationException,IllegalAccessException用不同的catch块分别处理不同的异常对象,要求catch块能够区别不同的异常对象通过catch块的参数来实现的。,当try语句块抛出一个异常对象e时,程序的流程首先转向第一个catch块检查当前异常对象是否可以被这个catch块所接收;如果e被第一个catch块所接收,则程序直接跳转到这个catch语句块中,语句块执行完毕后忽略try块中尚未执行的语句和其他的catch块,直接执行之后的语句;如果e与第一个catch块不匹配,系统将自动转到第二个catch块进行匹配,如果第二个仍不匹配,就转向第三个直到找到一个可以接收e的catch块,完成流程的跳转。,try语句块catch(Exception1 e1)catch(Exception2 e2)catch(Exception3 e3),异常对象e能否被一个catch语句块所接收,看该异常对象e与catch块的形式参数是否匹配,如果:(1)异常对象与参数属于相同的异常类。or(2)异常对象属于参数异常类的子类。or(3)异常对象实现了参数所定义的接口。则异常对象将被接收。,如果所有的catch块都不能与当前的异常对象e匹配,则说明当前方法不能处理这个异常对象e,程序流程将返回到调用该方法的上层方法。如果这个上层方法中定义了异常对象e相匹配的catch块,流程就跳转到这个catch块中;否则继续回溯更上层的方法。如果所有的方法中都找不到合适的catch块,则由系统来处理这个异常对象。通常中止程序的执行,退出虚拟机返回操作系统,并在标准输出上打印相关的异常信息。,try语句块catch(Exception1 e1)catch(Exception2 e2)catch(Exception3 e3),假设try块中所有语句的执行都没有引发异常,则所有的catch块都会被忽略而不予执行。,try语句块catch(Exception1 e1)catch(Exception2 e2)catch(Exception3 e3),在catch块处理不同的异常时:(1)catch块中的语句应根据异常的不同而执行不同的操作,通常应该打印异常和错误的相关信息,包括异常名称、产生异常的方法名等。(2)由于异常对象与catch块的匹配是按照catch块的先后排列顺序进行的,所以在多异常处理时应设计各catch块的排列顺序。越具体的异常的catch块应放在越前面,而可以与多种异常相匹配的catch块应放在较后的位置。,class TestArray private int i;private int array=1,2,3,4,5;void ml()while(true)i=(int)(Math.random()*10)-5;(以随机数为分母的除法结果是:+100/i);(数组array+i+的值是:+arrayi);,public class Temp public static void main(String args)TestArray a=new TestArray();try a.ml();catch(ArrayIndexOutOfBoundsException e1)(数组下标越界);catch(ArithmeticException e2)(运算错误,分母为0);e2.printStackTrace();(程序结束。);,1.Java异常处理2.Java输入输出,2.Java输入输出,任何一种计算机程序都需要进行输入输出处理,比如从键盘读取数据、保存或读入一个文件、在网络连接上读取数据等等。Java的输入输出处理封装在java.io包中,包含了不同情况下完成流式输入输出的类。利用输入输出类,Java程序可以实现多种输入输出操作和复杂的文件与目录管理。,2.Java输入输出,流:指在计算机的输入与输出之间运动的数据序列。输入流代表从外设流入计算机的数据序列;输出流代表从计算机流向外设的数据序列。流式输入输出数据的获取和发送均沿数据序列顺序进行:每一个数据都必须等待排在它前面的数据读入或送出之后才能被读写;每次读写操作处理的都是序列中剩余的未读写数据的第一个,不能随意选择输入输出的位置。,2.Java输入输出,输入流:与输入端(数据源)连接,调用read方法从输入端获得数据。数据源:终端键盘、文件、内存区域或另一个输入流对象。输入流的数据源是另一个输入流的数据时,可以对前一个输入流的数据做进一步的处理或转换加强输入功能。,2.Java输入输出,输出流:与输出端(目的地)连接,调用write方法向输出端输出数据。输出端:终端显示器、文件、内存区域或另一个输出流对象。输出流的输出为另一个输出流的数据时,对输出流的数据进行进一步的处理或转换加强输出功能。,2.Java输入输出,输入输出流序列中的数据既可以是未经加工的原始二进制数据,也可以是经一定编码处理后符合某种格式规定的特定数据,如字符流序列、数字流序列等。根据不同的数据、不同的数据序列方向,输入输出流的属性和处理方法也不同,在Java的输入输出类库中,有各种不同的输入输出类。,2.Java输入输出,Java中最基本的输入输出流类:基本输入流InputStream和基本输出流OutputStream。这两个类是最基本的输入输出功能的抽象类,其他所有输入流类都是继承了InputStream的基本输入功能、并根据自身属性对这些功能加以扩充的InputStream类的子类;其他所有输出流类也都是继承了OutputStream的基本输出功能并加以扩展的OutputStream的子类。所有的输入输出流类都是Java的基本输入输出类的子类。,2.Java输入输出InputStream,public abstract class InputStream extends Object implements Closeable字节输入流的所有类的父类,2.Java输入输出InputStream,当程序需要从外设中读入数据时,应该创建一个适当的输入流类的对象来完成与该外设(如键盘、磁盘文件或网络套接字等)的连接;然后再调用对象的特定方法(如read()来实现对相应外设的输入操作。InputStream是抽象类,在实际程序中创建的输入流都是InputStream子类的对象,由子类对象来实现与外设数据源的连接。InputStream子类的对象可以调用它继承的read()方法,从输入流读入数据。,2.Java输入输出InputStream,read()方法:逐字节地读取输入数据只能把数据以二进制的原始方式读入,不能分解、重组这些数据,使之变换、恢复到原来的有意义的状态。public int read():从输入流的当前位置处读入一个字节的二进制数据,然后以此数据为低位字节,配上一个全零字节合成为一个16位的整型量后返回。如果当前位置没有数据,则返回-1。public int read(byte b):从输入流的当前位置连续读入多个字节保存在字节数组b中,返回所读的字节的数目。,2.Java输入输出InputStream,定位输入位置指针:每个输入流都有一个位置指针,它在流刚被创建时产生并指向流的第一个数据,以后每次读操作都是在当前位置指针处执行;随着流操作的执行,位置指针自动后移,指向下一个未被读取的数据。位置指针决定read()方法在输入流中读到哪个数据。InputStream中用来控制位置指针的方法有:public long skip(long n):使位置指针从当前位置向后跳过n个字节;public void mark(int readlimit):在当前位置指针处做一个标记;readlimit规定了一个上限,当从流中读取的字符数超过这个上限时,利用reset方法将不能返回到这个标记处。public void reset():将位置指针返回到标记的位置。,2.Java输入输出InputStream,public void close():输入流使用完毕后,断开Java程序与外设数据源的连接,释放此连接所占用的系统资源。,2.Java输入输出OutputStream,Output Stream:抽象类,所有字节输出流的父类。当Java程序需要向某外设(如屏幕、磁盘文件或另一台计算机)输出数据时,应该创建一个新的输出流对象来完成与该外设的连接,然后利用OutputStream提供的write()将数据顺序写入到外设上。OutputStream是不能实例化的抽象类,创建的输出流对象应该是OutputStream的某个子类。,2.Java输入输出OutputStream,public abstract class OutputStream extends Object implements Closeable,Flushable,2.Java输入输出OutputStream,向输出类写入数据:也是顺序写,只有前面的数据已被写入外设时,才能输出后面的数据。将原始数据以二进制的方式,逐字节地写入输出流所连接的外设中,不能对所传递的数据完成格式或类型转换。public void write(int b):将参数b的低位字节写到输出流。public void write(byte b):将字节数组b中的全部字节顺序写到输出流。,2.Java输入输出OutputStream,public void flush():强制清空缓冲区并执行外设写操作。对缓冲流式输出来说,write()方法所写的数据并没有直接传到与输出流相连的外设上,而是先暂存在流的缓冲区中,等到缓冲区中的数据积累到一定的数量,再统一执行一次向外设的写操作把它们全部写到外设上。这样处理可以降低计算机对外设的读写次数,提高系统的效率。但是在有些情况下,缓冲区中的数据不满时就需要将它写到外设上,使用flush()方法。public void close():关闭输出流。当输出操作完毕时,调用close方法来关闭输出流与外设的连接并释放所占用的系统资源。,2.Java输入输出Reader和Writer,Reader类和Writer类:面向字符读写的抽象类,用于对字符数据流的输入输出操作。,2.Java输入输出Reader,public abstract class Reader extends Object implements Readable,Closeable,2.Java输入输出Writer,public abstract class Writer extends Object implements Appendable,Closeable,Flushable,以下介绍几种具体的输入输出子类,2.Java输入输出InputStream子类,ByteArrayInputStream(byte buf)字节数组输入流输入流的数据源为字节数组buf(内存中),程序通过输入流从数据源获取数据。不常用,2.Java输入输出InputStream子类,public class FileInputStream extends InputStream文件输入字节流以字节为单位对文件顺序读操作,import java.io.*;public class Temp static FileInputStream fin;static byte b;public static void main(String args)int i;try fin=new FileInputStream(file.txt);catch(FileNotFoundException e)System.out.println(No file.txt);System.exit(0);try i=fin.available();if(i 0)b=new bytei;fin.read(bb);System.out.println(new String(b);fin.close();catch(IOException e)System.out.println(file.txt read over);System.out.println(program over);,通常用FileReader,而不用FileInputStream,2.Java输入输出InputStream子类,FilterInputStream(InputStream in)过滤输入字节流(以另一个输入流in为数据源):在输入数据的同时能对所传输的数据进行指定类型或格式的转换,可实现对二进制字节数据的理解和编码转换。BufferedInputStream(InputStream in)缓冲输入字节流:增加了缓冲区,支持了mark和reset方法,提高了输入效率;DataInputStream(InputStream in)数据输入字节流:带格式的读操作,可以读取不同类型数据,如readByte(),readBoolean(),readShort(),readInt(),readChar()等。,2.Java输入输出OutputStream子类,ByteArrayOutputStream字节数组输出流FileOutputStream 文件输出字节流FilterOutputStream 过滤输出流DataOutputStream 数据输出流PrintStream 打印输出流,void print(boolean b):打印布尔值。void print(char c):打印字符。void print(char s):打印字符数组。void print(double d):打印双精度浮点数。void print(float f):打印浮点数。void print(int i):打印整数。void print(long l):打印 long 整数。void print(Object obj):打印对象。void print(String s):打印字符串。void println()();,2.Java输入输出Reader子类,Reader:以字符为单位的输入流,2.Java输入输出Reader子类,CharArrayReader(char buf):字符数组输入流以字符数组buf为输入数据源StringReader(String s):字符串输入流以字符串s为输入源InputStreamReader(InputStream in):字符输入流将字节流in转换为字符流BufferedReader(Reader in):缓冲字符输入流以字符流in为输入数据源,加入缓冲功能快速高效 readLine();read(char cbuf,int off,int len),import java.io.*;public class Temp public static void main(String args)BufferedReader in;in=new BufferedReader(new InputStreamReader(System.in);try in.mark(30);String ss=in.readLine();System.out.println(Your input:+ss);in.reset();ss=in.readLine();System.out.println(Again input:+ss);in.close();catch(IOException e)e.printStackTrace();,2.Java输入输出Reader子类,FileReader(String fileName):文件字符输入流从fileName指定的字符文件中读入数据。,import java.io.*;public class Temp public static void main(String args)BufferedReader in;String ss;try in=new BufferedReader(new FileReader(infile.txt);ss=in.readLine();while(ss!=null)System.out.println(Read a line:+ss);ss=in.readLine();in.close();catch(IOException e)e.printStackTrace();,2.Java输入输出Writer子类,Writer:以字符为单位的输出流,2.Java输入输出Writer子类,CharArrayWriter():字符数组输出流输出流的目的地为无名数组PrintWriter(OutStream out)或PrintWriter(Writer out)实现各种类型数据的打印输出,输出目的地为out对象。print(boolean b);print(char c);print(String s);println()按照平台的默认字符编码将 String.valueOf(boolean)生成的字符串转换为字节,并完全以 write(int)方法的方式写入这些字节。OutputStreamWriter(OutputStream out):字符输出流将字节流out转换为字符流输出BufferedWriter(Writer out):缓冲字符输出流以字符流out为输出目的地,加入缓冲功能快速高效 write(char cbuf,int off,int len);write(int c);write(String s,int off,int len);newLine(),2.Java输入输出Writer子类,FileWriter(String fileName)或FileWriter(File file):文件字符输出流向file或fileName指定的字符文件中输出数据。,import java.io.*;public class Temp public static void main(String args)PrintWriter out;try out=new PrintWriter(new FileWriter(out.txt,true);out.println(output data);out.println(3.1415926);out.close();catch(IOException e)e.printStackTrace();,import java.io.*;public class Temp public static void main(String args)BufferedWriter out;try out=new BufferedWriter(new FileWriter(out.txt,true);out.write(output data2);out.newLine();out.write(65);/只能输出字符串、字符数组和int值(表示char)out.close();catch(IOException e)e.printStackTrace();,2.Java输入输出标准输入输出,计算机通常有默认的标准输入设备(键盘)和标准输出设备(显示器)。Java程序与系统标准输入输出间进行数据通信(从键盘读入数据,或向屏幕输出数据)是频繁使用的操作,为此Java定义了流对象System.in和System.out,分别与系统的标准输入和标准输出相联系。in和out是系统类System的静态属性。,2.Java输入输出标准输入输出,标准输入System.in:InputStream类的对象。当程序中需要从键盘读入数据的时候,调用System.in的read()方法即可。使用()方法读入数据:()语句必须包含在try/catch块中,接收IOException异常。执行()方法将从键盘缓冲区读入1字节的数据,返回的却是2字节的整型量,这个整型量的低位字节是真正输入的数据,其高位字节是全零。作为InputStream类的对象,System.in只能从键盘读取二进制的数据,不能把这些比特信息转换为整数、字符、浮点数或字符串等复杂数据类型的量。,try char ch=();catch(IOException e),2.Java输入输出标准输入输出,当键盘缓冲区中没有数据时,执行()将导致系统转入阻塞(block)状态。在阻塞状态下,当前流程将停留在上述语句位置且整个程序被挂起,等待用户从键盘输入一个数据后,才能继续运行下去。,System.out.println(“Press any key to finish the program”);trychar test=();catch(IOException e)System.out.println(program finished);,2.Java输入输出标准输入输出,Java的标准输出System.out:PrintStream类的对象。PrintStream定义了向屏幕输送不同类型数据的方法print()和println()。public void println(数据类型 变量或对象);public void print(数据类型 变量或对象);,import java.io.*;public class Temp BufferedReader br;public static void main(String args)try br=new BufferedReader(new InputStreamReader(System.in);System.out.print(请输入一个整数:);int i=Integer.parseInt(br.readLine();System.out.print(您输入的整数是+i);catch(IOException e)System.err.println(e.toString();,总结:通常输入输出类进行IO操作的步骤:声明输入输出类的引用变量;创建输入输出类的对象,使输入输出类对象与特定的外设进行连接;调用输入输出类对象的read/write/print等方法,实现输入输出操作;操作完毕之后,关闭输入输出流。注意:创建对象、IO、关闭流时都可能产生异常,应该放到try/catch块中,来处理可能发生的异常情况。,