《JAVA输入输出和异常处理.ppt》由会员分享,可在线阅读,更多相关《JAVA输入输出和异常处理.ppt(74页珍藏版)》请在三一办公上搜索。
1、Java面向对象程序设计,怀化学院计算机系 张文,2023/11/7,2,IT企业文化,口号训练1、Java,Java,I Love You!2、我一定要学好Java!3、我一定能学好Java!,2023/11/7,3,第6章 输入/输出和异常处理,2023/11/7,4,思考问题,Why?Java程序必须同输入输出设备(文件、显示器、网络等)进行交互。How?,2023/11/7,5,6.1 I/O流,在Java中将不同来源和目标的数据统一抽象为流,通过对流对象的操作来完成I/O功能。Java中的流很灵活,可以连接到各种不同的源或目标,如磁盘文件、键盘(输入设备)、显示器(输出设备)、网络等
2、。,2023/11/7,6,流的层次,字节流,2023/11/7,7,流的层次,字符流 和 类 和 是抽象(abstract)类是基于文本的其它读写器的父类(superclasses)输入/输出流字节流读写器是基于字符,2023/11/7,8,6.1.3 字节流和字符流,根据流处理数据类型的不同也可以将其分为两类:字节流与字符流,下面列出了这两种流的不同之处。字节流:字节流以字节为基本单位来处理数据的输入/输出,一般都用于对二进制数据的读写,如声音、图像等。字符流:字符流以字符为基本单位来处理数据的输入和输出,一般都用于对文本类型数据的读写,如文本文件、网络中发送的文本信息等。虽然文本数据也可
3、以看作二进制数据,但一般采用字符流处理文本数据比采用字节流效率更高,也更方便。,2023/11/7,9,处理数据流的核心思想,处理数据流的核心思想能过循环处理每个数据单元,直到遇到结束符或出现异常(Exception)结束符在Unix操作系统下,键入Control-D表示数据流的结束在Windows操作系统下,键入Control-Z表示数据流的结束,2023/11/7,10,类 InputStream,类 是一个抽象(abstract)类,声明了从原始字节数据流读入数据的基本方法类中声明的方法:public abstract int read()throws IOException publi
4、c int read(byte data)throws IOException public int read(byte data,int offset,int length)throws IOException public long skip(long n)throws IOException public int available()throws IOException public void close()throws IOException public void mark(int readlimit)public void reset()throws IOException pu
5、blic boolean markSupported(),2023/11/7,11,类InputStream的成员方法read()读入单个无符号字节(unsigned byte)的数据,并返回一个整数类型(int)的值(与读入的无符号字节数据相对应)正常返回:介于0和255之间的一个数 如果遇到数据流结束,则返回-1public abstract int read()throws IOException,2023/11/7,12,下面的两个方法可以一次读入多个字节到数组中java.io.InputStream public int read(byte data)throws IOExcepti
6、on public int read(byte data,int offset,int length)throws IOException,2023/11/7,13,方法 available()给出可以读入的字节数这样在读数据之前就知道可以读入的字节数public int available()throws IOException,2023/11/7,14,当处理完数据流时,应当关闭该数据流,以便释放该数据流所关联的资源public void close()throws IOException,2023/11/7,15,类OutputStream,OutputStream 也是abstract
7、 类类中的成员方法:public abstract void write(int b)throws IOException public void write(byte data)throws IOException public void write(byte data,int offset,int length)throws IOException public void flush()throws IOExceptionpublic void close()throws IOException 有时输出流会先输出到缓存中,最后再一起将数据写到指定的位置(如文件)。方法flush()可以强
8、制进行输出,即强制将数据写到指定的位置(如文件/标准输出),2023/11/7,16,Print 数据流,类 是类FilterOutputStream的子类示例:System.out 和 System.err类PrintStream 的实例对象不会抛出(throws)异常(IOException)这个类“吃掉”(traps)所有的异常(IOExceptions),2023/11/7,17,|,2023/11/7,18,6.2 I/O流的使用,标准的I/O流|static PrintStream err 标准错误输出流static InputStream in 标准输入流static Print
9、Stream out 标准输出流,在Java语言中,键盘用stdin表示,监视器用stdout表示。它们均被封装在System类的类变量in和out中,分别对应于System.in和System.out。事实上,类变量in和out分别属于类InputStream和PrintStream,只是由于InputStream和PrintStream不能用new()方法直接创建,所以才在System类中声明为如右的3个类变量。,2023/11/7,19,6.2 I/O流的使用,JDK5.0开始提供了类似C语言中的格式化输出的printf()方法。public PrintStream printf(Str
10、ing format,Object args),2023/11/7,20,使用Scanner工具,Java 5添加了java.util.Scanner类,这是一个用于扫描输入文本的新的实用程序。它是以前的StringTokenizer和Matcher类之间的某种结合。由于任何数据都必须通过同一模式的捕获组检索或通过使用一个索引来检索文本的各个部分。于是可以结合使用正则表达式和从输入流中检索特定类型数据项的方法。这样,除了能使用正则表达式之外,Scanner类还可以任意地对字符串和基本类型(如int和double)的数据进行分析。借助于Scanner,可以针对任何要处理的文本内容编写自定义的语法
11、分析器。Scanner是SDK1.5新增的一个类,可是使用该类创建一个对象.,2023/11/7,21,Scanner的使用,Scanner reader=new Scanner(System.in);然后reader对象调用下列方法(函数),读取用户在命令行输入的各种数据类型:next.Byte(),nextDouble(),nextFloat,nextInt(),nextLine(),nextLong(),nextShot()上述方法执行时都会造成堵塞,等待用户在命令行输入数据回车确认.例如,拥护在键盘输入12.34,hasNextFloat()的值是true,而hasNextInt()的
12、值是false.NextLine()等待用户输入一个文本行并且回车,该方法得到一个String类型的数据。下面是一个实例:,2023/11/7,22,import java.util.*;public class Examplepublic static void main(String args)System.out.println(请输入若干个数,每输入一个数用回车确认);System.out.println(最后输入一个非数字结束输入操作);Scanner reader=new Scanner(System.in);double sum=0;int m=0;while(reader.ha
13、sNextDouble()double x=reader.nextDouble();m=m+1;sum=sum+x;System.out.printf(%d个数的和为%fn,m,sum);System.out.printf(%d个数的平均值是%fn,m,sum/m);,2023/11/7,23,6.2.3 过滤流,过滤流FilterInputStream和FilterOutputStream分别是InputStream和OutputStream的子类,而且它们也都是抽象类。FilterInputStream类和FilterOutputStream类都重写了超类InputStream和Outpu
14、tStream的方法。FilterInputStream和FilterOutputStream为读写处理数据的过滤流定义接口。其子类则进一步实现接口和方法。这些子类有以下几种。DataInputStream类和DataOutputStream类BufferedInputStream和BufferedOutputStream类LineNumberInputStream类PushbackInputStream类,2023/11/7,24,6.2.4 文件随机读写,RandomAccessFile类具有DataInputStream和DataOutputStream对象的所有功能。当程序把一个Ran
15、domAccessFile对象与一个文件关联时,程序从文件定位指针指定的位置开始读写数据,并且把所有数据当成基本数据类型来操作。使用RandomAccessFile除了可以读写文件中任意位置的字节外,还可以读写文本和Java的基本数据类型。,2023/11/7,25,随机访问文件方式可以在指定位置读/写字节内容RandomAccessFile 实例对象同时具有类DataInputStream和类DataOutputStream的功能类RandomAccessFile实现了接口DataInput和DataOutput类DataInputStream实现了接口DataInput类DataOutpu
16、tStream实现了接口DataOutput,2023/11/7,26,java.lang.Object|+-java.io.RandomAccessFilepublic class RandomAccessFileextends Objectimplements DataOutput,DataInput;,2023/11/7,27,当RandomAccessFile的实例对象与某个文件相关联在指定位置读取或写出数据,位置指定方法如下:void seek(long pos)基本数据类型数据具有固定字节数(如:double 8字节等等)这是Java基本数据类型数据的基本特点,2023/11/7,
17、28,当RandomAccessFile提供的构造方法 RandomAccessFile(String fname,String mode);RandomAccessFile(File fe,String mode);其中fname是文件名参数;mode是文件访问模式,有“r”和“rw”。,2023/11/7,29,当RandomAccessFile提供的主要读方法,2023/11/7,30,当RandomAccessFile提供的主要写方法,2023/11/7,31,示例:随机访问文件/J_RandomAccessFile.java,import java.io.IOException;im
18、port java.io.RandomAccessFile;public class J_RandomAccessFile public static void main(String args)try RandomAccessFile f=new RandomAccessFile(test.txt,rw);double d;for(int i=0;i10;i+)f.writeDouble(0.5*i);f.seek(16);f.writeDouble(0);f.seek(0);for(int i=0;i 10;i+)d=f.readDouble();System.out.println(+i
19、+:+d);/for循环结束 f.close();catch(IOException e)System.err.println(发生异常:+e);e.printStackTrace();/try-catch结构结束/方法main结束/类J_RandomAccessFile结束,2023/11/7,32,6.2.5 流的分割,流的分割是由StreamTokenizer类实现的。该类把一个流的内容划分成若干个token单位,一次可以读写一个token。token是文本分析算法可识别的最小单位(如单词、符号等)。一个StreamTokenizer对象可用于分析任何文本文件。它可以识别标识符、数字、引
20、号包围的字符串以及各种注释形式。尽管StreamTokenizer并不是从InputStream或OutputStream衍生的,但它只随同InputStream工作,所以十分恰当地包括在库的IO部分。StreamTokenizer类用于将任何InputStream分割为一系列“记号(Token)”。这些记号实际是一些断开的文本块,中间用我们选择的任何东西分隔。例如,记号可以是单词,中间用空白(空格)以及标点符号分隔。,2023/11/7,33,Reader和Writer,处理文本数据可以采用类 和 类 和 是抽象(abstract)类是基于文本的其它读写器的父类(superclasses)输
21、入/输出流字节流读写器是基于字符,2023/11/7,34,类中的成员方法类似于类中的成员方法类中的成员方法类似于类中的成员方法,2023/11/7,35,public void write(int c)throws IOException写出双字节的单个字符(其值范围:从0到65535)。其它write方法:public void write(char text)throws IOException public abstract void write(char text,int offset,int length)throws IOException public void write(S
22、tring s)throws IOException public void write(String s,int offset,int length)throws IOException,2023/11/7,36,带缓存的Reader可以提高读取数据性能,类 java.io.BufferedReader 是类java.io.Reader的子类|当读取数据量很大时,一个很好的方法是:通过类BufferedReader,这时需要给Reader的子类(如:FileReader)“外包”上类BufferedReader示例:BufferedReader br=new BufferedReader(n
23、ew FileReader(test);,2023/11/7,37,类 是类的子类:带有行号信息java.lang.Object|+-java.io.Reader|+-java.io.BufferedReader|+-java.io.LineNumberReader类LineNumberReader中的部分方法public LineNumberReader(Reader in)public LineNumberReader(Reader in,int size)public void setLineNumber(int lineNumber)public int getLineNumber()
24、,2023/11/7,38,类 InputStreamReader,类 起到了从输入流到Reader的桥梁作用示例:InputStreamReader isr=new inputStreamReader(System.in);,2023/11/7,39,类 OutputStreamWriter,类 起到了从输出流到Writer的桥梁作用示例:OutputStreamWriter osw=new OutputStreamWriter(System.out);,2023/11/7,40,读取文件内容,类 FileReaderjava.lang.Object|+-java.io.Reader|+-j
25、ava.io.InputStreamReader|+-java.io.FileReader示例:FileReader fr=new FileReader(test);,2023/11/7,41,写文本文件,类 java.lang.Object|+-java.io.Writer|+-java.io.OutputStreamWriter|+-java.io.FileWriter示例:FileWriter fw=new FileWriter(“test);,2023/11/7,42,写文本文件,类 java.lang.Object|+-java.io.Writer|+-java.io.OutputS
26、treamWriter|+-java.io.FileWriter示例:FileWriter fw=new FileWriter(“test);,2023/11/7,43,6.3 对象的序列化,Java的对象序列化用于将一个实现了Serializable接口的对象转换成一组byte,这样以后要用这个对象时候,就能把这些byte数据恢复出来,并据此重新构建那个对象了。这一点甚至在跨网络的环境下也是如此,这就意味着序列化机制能自动补偿操作系统方面的差异。也就是说,可以在Windows机器上创建一个对象,序列化之后,再通过网络传到Unix机器上,然后在那里进行重建,而不用担心在不同的平台上数据是怎样表
27、示的,byte顺序怎样,或者别的什么细节。,2023/11/7,44,6.3.1 存储对象,Java序列化技术可以将一个对象的状态写入一个byte流里,并且可以从其他地方把该byte流里的数据读出来,重新构造一个相同的对象。这种机制允许将对象通过网络进行传播,并可以随时把对象存储到数据库、文件等系统里。Java的序列化机制是RMI、EJB、JNNI等技术的技术基础。并非所有的Java类都可以序列化,为了使指定的类可以实现序列化,必须使该类实现接口java.io.Serializable。需要注意的是,该接口什么方法也没有。实现该类只是简单的标记类准备支持序列化功能。,2023/11/7,45,
28、6.3.2 对象的序列化,Java1.1以后添加了对象序列化机制,可以把实现了Serializable接口的对象序列化。Serializable接口中没有定义任何方法,只是一个特殊的标记,用来告诉Java 编译器,这个对象参加了序列化的协议,可以把它序列化。因此一个类实现Serializable接口时,并不需要实现任何针对该接口的方法,,2023/11/7,46,6.3.3 对象序列化中的一些问题,在对对象序列化的过程中需要注意以下两个问题。(1)性能问题为了序列化类A的一个实例对象,所需保存的全部信息如下。与此实例对象相关的全部类的元数据(metadata)信息;因为继承关系,类A的实例对象
29、也是其任一父类的对象。因而,需要将整个继承链上的每一个类的元数据信息,按照从父到子的顺序依次保存起来。(2)版本信息当用readObject()方法读取一个序列化对象的byte流信息时,会从中得到所有相关类的描述信息以及示例对象的状态数据;然后将此描述信息与其本地要构造的类的描述信息进行比较,如果相同则会创建一个新的实例并恢复其状态,否则会抛出异常。这就是序列化对象的版本检测。,2023/11/7,47,6.4 文 件 管 理,前面的章节介绍了Java中的各种I/O流,在使用I/O流的过程中很多情况下源与目标都是文件。因此,本节将介绍在Java中如何获取目录、文件的信息以及对目录、文件进行管理
30、。,2023/11/7,48,6.4.1 File类简介,Java中专门提供了一个表示目录与文件的类java.io.File,通过其可以获取文件、目录的信息,对文件、目录进行管理。File类一共提供了4个构造器,,2023/11/7,49,6.4.2 使用File类,下面的例子创建MyFile文件夹,接着在MyFile文件夹下创建ChildFile.txt文件,并向文件中写入字符串。通过使用java.io包中提供的File类可以方便地对文件、目录进行管理。实际开发中如果有需要,可以参照本例进行开发。File类中的常用方法见P189的表,2023/11/7,50,public class Cre
31、ateFile public static void main(String args)tryFile f1=new File(mydir);f1.mkdir();for(int i=0;i20;i+)BufferedInputStream bin=new BufferedInputStream(new FileInputStream(CreateFile.java);BufferedOutputStream bout=new BufferedOutputStream(new FileOutputStream(new File(f1,CreateFile.java);int n;while(n
32、=bin.read()!=-1)bout.write(n);bin.close();bout.close();f1=new File(f1,mydir);f1.mkdir();catch(Exception e)e.printStackTrace();,2023/11/7,51,实训题目,运行D盘下的CreateFile.java文件删除D盘下mydir文件夹。,2023/11/7,52,参考代码:import java.io.*;public class DeleteFile void delete(File f)if(f.isDirectory()String files=f.list()
33、;for(int i=0;ifiles.length;i+)delete(new File(f.getAbsoluteFile(),filesi);f.delete();public static void main(String args)DeleteFile app=new DeleteFile();app.delete(new File(mydir);,2023/11/7,53,Java 异常处理(Exception)基础,异常(Exception)?异常(Exception)是正常程序流程所不能处理或没有处理的异常情况或异常事件。在有些书中,异常也称作例外。,2023/11/7,54,
34、格式,在try语句块中包含可能会产生异常的语句紧接着若干个catch语句块,进行异常处理catch语句块与finally语句块至少存在一个,try/可能会抛出异常的代码catch(ExceptionType ref)/异常处理代码finally/,2023/11/7,55,为什么需要异常?,强制程序异常/错误处理同时指定需要异常的种类异常处理模型提供了一种统一处理异常/错误的模式传统程序方法:设置标志位,或返回错误码,分别处理各种异常情况。但在编程时常常出现这样的情况:忘了对某些异常情况进行处理,尤其是当存在多个分支或者多个开发人员共同开发程序时。简化对异常情况的处理,减少if-else语句,
35、2023/11/7,56,什么时候会发生异常?,数组的下标越界打开不存在的文件网络无法连接操作数超出所要求的范围少了所需加载的类,自定义异常,要求程序处理,2023/11/7,57,处理异常的几种常用方法,一旦捕获异常,马上进行处理重新抛出异常捕获异常,但并不处理通过语句System.exit()退出应用程序,2023/11/7,58,异常(Exceptions)类型,常见异常内存耗尽数组下标越界除数为0非法的参数(方法的参数),2023/11/7,59,异常(Exception)的层次结构,2023/11/7,60,运行时发生的异常(RuntimeExceptions),异常随时都可以发生A
36、rrayIndexOutOfBoundsExceptionNullPointerException定义了引用,但不指向任何对象(object)ClassCastException数据类型间的转换不合法良好的编程习惯,可以减少很多异常的发生,2023/11/7,61,受检异常和非受检异常,受检异常必须在方法声明时通过throws列出在编译时就能被检测出非受检测异常不必在throws列表中错误(Errors)和运行时异常(RuntimeExceptions)受检异常,必须处理才能通过编译运行时异常只有在运行时才能被发现错误常常指的是致命性错误,常常也无法处理,2023/11/7,62,处理多种异常
37、(Exception)类型,如果含有多外catch语句块,则异常会被第一个与其相匹配的catch语句块处理,2023/11/7,63,finally 语句块,在异常处理过程中,finally 语句块总是会被执行到:无论有没有异常发生,也无论有没有异常被捕捉到可选项:finally 语句块,通常位于catch 语句块的后面可以用来释放try语句块中获得的资源例如,关闭在try语句块中打开的文件,2023/11/7,64,throws 列表,在方法的声明处列出所有的受检异常返回类型 方法名(参数列表)throws 异常类型1,异常类型2,/方法体在本方法内就可以不处理这些异常调用该方法的方法就必须
38、处理这些异常示例:public static void g()throws Exception throw new Exception();/方法g结束,2023/11/7,65,异常处理:捕捉-或者-声明,如果一个方法调用一个抛出受检异常的方法(含有throws列表的方法),则该方法必须捕捉这些受检异常,或通过throws列表声明这些异常,2023/11/7,66,重新抛出异常,如果catch语句块不处理某种异常,可以重新抛出异常抛出异常的方法:throw e;由其外层的try-catch 语句块处理,2023/11/7,67,6.5 异 常 处 理,有过一些经验的开发人员都能体会到,在开发
39、项目的过程中,开发核心业务代码只占了20%30%的时间,而用于开发容错代码的时间却高达70%80%,这大大降低了开发效率。Java中提供的异常处理机制,可以在一定程度上解决这个问题。通过使用异常处理机制,可以使容错代码的开发变得轻松。本章将对Java中的异常处理机制进行详细的介绍,主要包括基本的异常处理、异常的层次结构、定义自己的异常等内容。,2023/11/7,68,6.5.1 异常处理概述,Java中定义了很多异常类。每个异常类都代表了一种或多种运行错误,异常类中包含了该运行的错误信息和处理错误的方法等内容。每当Java程序运行过程中发生一个可识别的运行错误时,即产生一个异常。Java采取
40、“抛出-捕获”的方式,一旦一个异常产生了,Runtime环境和应用程序抛出各种标准类型和自定义的异常,系统就可以捕获这些异常,并且有相应的机制来处理它,确保不会产生死机、死循环或其他损害,从而保证了整个程序运行的安全性。这就是Java的异常处理机制。,2023/11/7,69,6.5.2 异常的层次结构,当异常发生时,Java会将该异常包装成一个异常类的对象,并将其引用作为参数传递给相应的catch语句,这样在catch语句中就可以对这个异常对象进行操作。本节将系统地介绍异常类的层次结构,主要内容包括捕获异常与未捕获异常两个方面。1捕获异常Java类库中有一个java.lang.Throwab
41、le类,继承自java.lang.Object类,是所有异常类的超类。2未捕获异常,2023/11/7,70,2023/11/7,71,6.5.3 自定义异常,从前面的例子可以看出,用throw语句抛出的异常不一定是捕获的,也可以是自己创建的。Java中每个异常类都代表一种特定的情况,有时系统中已有的异常类型不能满足使用的需要。这时,就需要抛出自定义的异常对象,本节将介绍如何创建以及使用自己定义的异常类,以及显性再抛出在实际开发中的意义与作用。1创建自己的异常类2使用自定义的异常类,2023/11/7,72,实训,P206实验二P208实验四,2023/11/7,73,6.6 小结,本章简要地介绍了Java的输入/输出和异常处理。概述了Java用于输入输出的I/O流以及几种主要I/O流类的使用。然后分别介绍了Java对象序列化机制和文件管理。最后介绍了Java中的异常处理,通过对异常的及时处理,可以提高程序运行的稳定性。通过本章的学习,读者可以掌握Java中进行输入输出的方法和异常处理机制,进一步加深对Java知识的理解和应用。,2023/11/7,74,Welcome to Java,Thank You,