Download presentation
Presentation is loading. Please wait.
1
JAVA 网络编程基础
2
第一部分 JAVA程序设计基础 第五章 异常处理 第六章 Java的可重用类
3
第一章 计算机语言概述 第一节 程序设计语言 第二节 语言翻译程序 第三节 Java虚拟机与运行环境 第四节 Java程序的运行
第一章 计算机语言概述 第一节 程序设计语言 第二节 语言翻译程序 第三节 Java虚拟机与运行环境 第四节 Java程序的运行 第五节 Java程序的开发、执行流程 小结 习题
4
第二章 Java的开发环境 第一节 Java的开发环境 第二节 JDK的安装、环境配置及使用 第三节 JBuilder 6的开发环境 小结
习题
5
第三章 Java语言基础 第一节 一个简单的Java程序实例 第二节 标识符、注释和分隔符 第三节 变量和常量 第四节 基本类型
第二节 标识符、注释和分隔符 第三节 变量和常量 第四节 基本类型 第五节 运算符及表达式 第六节 运算符的优先级 第七节 数据类型转换 第八节 语句和复合语句 小结 习题
6
第四章 Java面向对象的程序设计 第一节 面向对象的理论基础 第二节 类与对象的基本概念 第三节 Java的类 第四节 继承
第一节 面向对象的理论基础 第二节 类与对象的基本概念 第三节 Java的类 第四节 继承 第五节 对象的创建及使用 第六节 null , this 和 super 第七节 接口 第八节 包 小结 习题
7
第五章 5.1 异常类的层次 5.2 throws抛出异常 5.3 throw抛出异常 5.4 try-catch异常处理
5.1 异常类的层次 5.2 throws抛出异常 5.3 throw抛出异常 5.4 try-catch异常处理 5.5 Finally子句 5.6 正确地使用异常 小结 习题
8
第五章 异常处理 一 为什么要引入异常 二 异常的几个概念(处理机制) 三 异常处理 四 小结
9
为什么要引入异常机制 当程序运行的时候,经常会由于各种不可避免的原因而产生错误。
一个好的程序应该可以自己处理这些错误,而不是使整个程序全部瘫痪 。 Java把运行中各种可能出现的错误都看作异常并提供了异常处理的能力(异常处理)。
10
异常的几个概念 异常机制的过程:抛出异常——捕捉异常
1 当出现了一些错误,方法都会产生一个异常对象,这个异常对象将交由运行系统来处理。此过程就称为抛出(throwing)异常。 2 接着,运行系统开始寻找合适的处理方法,来处理这个异常。如果系统找到了一个适合的处理该异常方法,这一过程就叫捕获异常。 包括:系统抛出 用户自定义抛出
11
Non-RuntimeException
异常类的结构 Object Throwable Error Exception Non-RuntimeException RuntimeException IOException
12
异常类常用的方法 public Exception()
public Exception(String s):该参数一般表示该异常对应的错误的描述 public String toString(): 返回描述当前异常对象信息的字符串 。 public String getMessage():返回描述当前异常对象信息的详细信息。 public void printStackTrace():打印当前异常对象使用堆栈的轨迹。
13
异常处理机制的语法支持 格式: 异常处理由try/catch/[finally]三个语句组成的: ⑴ try包含可能出现异常的语句块
⑵ 一个或多个catch块紧随try{}块,每个catch块通常处理指定类型的异常 ⑶ finally引导块紧随catch块后,主要用于清理现场(可有可无) 注意:finally块总是执行,catch块不一定执行 格式: try { ...... }catch( ExceptionName1 e ) { } catch( ExceptionName2 e ) { ......} finally
14
自定义的抛出异常 自定义抛出语句 throw 异常类对象; 说明: ⑴ throw之后必须接异常类(Throwable或其子类)的实例。
⑶ 抛出语句应在满足一定条件时执行(如与if连用) ⑷ 含有throw语句的方法,抛出的异常一般由调用者处理
15
声明可能生成但没处理的异常 指定函数抛出的异常
方法内的代码有可能发生异常而又不自己进行处理时,就必须在声明方法时一并指出方法有可能发生的异常,以便该方法的调用者或系统的预设处理方法能够捕获并处理由方法抛出的异常。 声明格式: 返回类型 方法名([参数列表]) throws 异常类列表 { <方法体> } 注意: Error和RuntimeException类及它们的子类一般不需在方法声明中指定(属Java不检查异常)
16
小结 异常处理把错误集中起来统一处理。程序员只需要说明何处可能出现异常,如何处理即可。
17
throws抛出异常和方法说明联系在一起,是针对以下况:
方法中出现的异常由catch语句捕获,进行处理。
18
try-catch异常处理机制。 当try体中发生了一个异常,try-catch语句就会自动在try体后面的各个catch语句中,找出与该异常类相匹配的参数,就执行包含这一参数的catch语句中的Java代码。 不论try块中是否发生了异常,是否执行过catch语句,都要执行finally语句,可以说是为异常处理事件提供的一个清理机制。
19
第六章 Java的可重用类 第一节 Java可重用类的结构 第二节 Java语言包(Java.lang) 第三节 常用容器数据类型
第三节 常用容器数据类型 第四节 输入输出包java.io 小结 习题
20
5.1 异常类的层次 异常处理的概念 当程序运行的时候,经常会由于各种不可避免的原因而产生错误。例如除数为零、文件找不到而无法读写等等。Java提供的丰富的异常情况处理机制通常叫异常处理。异常处理把Java程序各种可能出现的错误都看作异常,集中起来统一处理。程序员只许要说明何处可能出现异常,如何处理即可。
21
5.1 异常类的层次 异常类的层次结构如图5-1所示。
异常在Java中也是作为类的实例的形式出现的。Java中的所有的异常类都是从Throwable类派生出来的。Throwable类有两个直接子类:java.lang.Error和java.lang.Exception。 异常类的层次结构如图5-1所示。 Error类及其子类主要用来描述一些Java运行时刻系统内部的错误或资源枯竭导致的错误。普通的程序不能从这类错误中恢复,也无法抛出这种类型的错误,这类错误出现的几率是很小的。 另一个异常类的子类是Exception类和它的子类。在编程中错误的处理主要是对这类错误的处理,如除数为零、数组下标越界等。类Exception是普通程序可以从中恢复的所有规范了的异常的父类。
22
5.1 异常类的层次 Exception类又有两个子类:RuntimeException和Non_RuntimeException。
RuntimeException是程序员编写程序不正确所导致的异常,是在Java系统运行过程中出现的异常,如除数为零等。由于运行时异常可能会出现在程序的任何地方,而且出现的可能性非常大,因而由程序本身去检测运行异常出现与否,将会使程序的开销过大,所以编译器并不要求程序去说明或捕获运行时异常。RuntimeException类的异常的产生是程序员的过失,理论上,程序员经过检查和测试可以查出这类错误。
23
5.1 异常类的层次 N0_RuntimeException类的异常包括:格式不正确的URL、试图为一个不存在的类找到一个代表它的类的对象。
Non_RuntimeException是指可以由编译器在编译时检测到的、可能会发生在方法执行过程中的异常,如找不到指定名字的类或者界面,不是程序本身的错误,如果这些异常情况没有发生,程序本身仍然是完好的。如果程序不能适当地处理可能会引发运行异常的语句,则程序将不能通过编译器的编译。 Java提供了两种不同的异常抛出机制: throws抛出异常——间接抛出异常 throw 抛出异常——直接抛出异常
24
Non-RuntimeException
Object Throwable Error Exception Non-RuntimeException RuntimeException IOException 图5-1 异常类的层次结构
25
5.2 throws抛出异常 带throws异常说明的方法说明形式如下: … 方法名(…) [throws 异常类列表] { 方法体 }
方法抛出的异常类是throws子句中指定的异常类或其子类。比如在方法的说明中指明方法可能产生IOException,但是实际上可能抛出的异常或许是EOFException类的实例,这些异常都是IOException的子类。 并不是所有可能发生的异常都要在方法的说明中指定,从Error类中派生出的异常和从RuntimeException类中派生的异常就不用在方法声明中指定。这两类异常属于不检查异常。不检查异常则是那些无法干预的异常。 Java中的另
26
5.2 throws抛出异常 一类异常是检查异常,检查异常是那些在程序中应该处理的异常,程序完全可以避免的异常(比如数组越界错误)。而throws异常说明必须指定有可能发生的检查异常。 在下列情况下Java方法抛出异常: (1)调用的方法抛出了异常; (2)检测到了错误并使用throw语句抛出异常; (3)程序代码有错误,从而异常,比如数组越界错误。 例5.1 throws抛出一个异常 class Test {…… public String getInput() throws IOException; {…… // throws一个异常 }
27
5.2 throws抛出异常 例5.2 throws多个异常 class Animation { // throws多个异常
public Image loadImage(String s) throws EOFException, MalformURLException { …… }
28
5.3 throw抛出异常 throw语句的形式为: throw 异常类的实例; 例5.3
在程序中使用throw语句(注意,这里是throw而不是throws)来抛出异常,该异常可以在该程序中进行捕获、处理,也可以在调用该方法者捕获、处理。 throw语句的形式为: throw 异常类的实例; 例5.3 import java.io.IOException; public class ThrowException { public static void main(String args[]) { try { String s=getInput(); //getInput() throw抛出异常 System.out.println(s); }
29
5.3 throw抛出异常 catch(IOException e) // 捕获异常
{System.out.println(e.getMessage()); } } static String getInput() throws IOException{ // getInput()方法抛出异常,因为在它的方法体中调用的 //read方法抛出异常,并且该方法体本身使用throw抛出异常 char[] buffer =new char[20]; int counter = 0; boolean flag =true; while(flag) { buffer[counter] =(char)System.in.read();
30
5.3 throw抛出异常 if(buffer[counter]=='\n') flag = false; counter++;
if(counter>=20){ IOException ae =new IOException("buffer is full"); //构造异常实例 throw ae; //抛出异常类的实例 } return new String(buffer);
31
5.3 throw抛出异常 上面的例中说明了一个方法getInput(),它用来获取从键盘输入的字符,并以字符串对象的形式返回。并且从键盘输入的字符数不能多于20个,否则就抛出一个IOException异常。由于在方法getInput()中,可能会产生IOException异常,所以在方法的说明中必须指明方法可能抛出异常: static String getInput() throws IOException 在方法getInput()中,可能产生异常的地方有两处,一是Java的InputStream类的read()方法。InputStream类的 read()方法如下所示: public abstract int read() throws IOException 但是在方法getInput()中,我们并没有捕获和处理这个异常:buffer[counter]= (char)System.in.read();
32
5.3 throw抛出异常 另一个可能产生异常的地方是方法中的while循环: while(flag)
{buffer[counter] = (char)System.in.read(); if(buffer[counter]= =‘\n’) flag = false; counter++; if(counter>=20) {IOException ae =new IOException(“buffer is full”); throw ae; }
33
5.3 throw抛出异常 在这个循环中,如果输入的字符数大于20,就会抛出一个IOException异常(这里只是作为抛出异常的一个示范,实际上这并不是IOException异常)。而在方法main中将捕获这个异常,并打印出异常的信息。如果没有异常发生,就打印输入得到的字符串。 可以看出,抛出异常有这样三步: (1)确定异常类; (2)创建异常类的实例; (3)抛出异常。
34
5.4 try-catch异常处理 利用try-catch语句可以说明抛出异常的部位,同时又说明捕获、处理的办法。
{ 语句系列 } catch(异常类1 变量名1){ catch处理 } …… catch(异常类n 变量名n){ catch处理 } [finally 语句] 其中: try之后的复合语句说明抛出异常的部位,该部位含有抛出异常的语句,如调用抛出异常的方法等; catch(异常类 变量名) 是按抛出的异常类进行捕获; catch处理是对捕获的异常作相应的处理; 如果有finally部分,其后的语句是最后必然要执行的语句。
35
5.4 try-catch异常处理 例 5.4 try-catch异常处理 : import java.io.*;
public class Try_catch {public static void main (String args[]) {FileInputStream fis=null; try { fis=new FileInputStream(“c:/filename.txt”); } // FileInputStream 方法抛出异常,所以位于try体内 catch(FileNotFoundException e) //捕获FileNotFoundException异常 {System.out.println("catchexception"+e.getMessage());}
36
5.4 try-catch异常处理 try { int c=fis.read(); //调用的read()方法抛出异常 }
catch(IOException e) //捕获IOException异常 System.out.println("catchexception:"+e.getMessage()); 上述try-catch语也可改写成:
37
5.4 try-catch异常处理 try //有多个语句抛出异常 {
fis=new FileInputStream(“c:/fileName.txt”); //filename.txt指要读入的文件名 int c=fis.read (); //读字节整数 } catch (FileNotFoundException e) { //捕获FileNotFoundException异常 System.out.println(“catchexception:”+e.getMessage()); catch(IOException e) //捕获IOException异常 {System.out.println(“catchexception:”+e.getMessage()); } //在这里用e.getMessage()得到有关异常的信息
38
5.4 try-catch异常处理 当catch前面的try块中发生了一个异常,try-catch语句就会自动在try块后面的各个catch块中,找出与该异常类相匹配的参数。当参数符合以下三个条件之一时,就认为这个参数与产生的异常相匹配: (1) 参数与产生的异常的属于一个类; (2) 参数是产生的异常的父类; (3) 参数是一个接口时,产生的异常实现了这一接口。 当产生的异常找到了第一个与之相匹配的参数时,就执行包含这一参数的catch语句中的Java代码,执行完catch语句后,程序恢复执行,但不会回到异常发生处理继续执行,而是执行try-catch结构后面的代码。
39
5.5 finally子句 finally语句可以说是为异常处理事件提供的一个清理机制,一般是用来关闭文件或释放其他的系统资源,作为try-catch-finally结构的一部分,可以没有finally语句,如果存在finally语句,不论try块中是否发生了异常,是否执行过catch语句,都要执行finally语句。 带有finally子句的try-catch-finally语句的形式如下: try { … } //…是正常执行的代码, 可能产生异常 catch (异常类1 e1) { … } //…是异常类1的处理代码 catch (异常类2 e2) { … } //…是异常类1的处理代码 …… catch (异常类n en) { … } //…是异常类1的处理代码 finally { … } //…是执行清除工作的语句
40
5.5 finally子句 带有finally子句的try-catch-finally语句无论在try块中是否产生异常,也不管产生的异常是否会被捕获,finally中的语句最终都会被执行。具体的执行过程如下: (1) try块中的语句没有产生异常。在这种情况下,Java首先执行try块中的所有的语句,然后执行finally子句中的代码,最后执行try…catch..finally块后面的语句; (2) try块中的语句产生了异常,而且此异常在方法内被捕获。在这种情况下,Java首先执行try块中的语句,直到产生异常处,然后跳过此try块中剩下的语句,执行捕获此异常的catch子句的处理代码;然后执行finally子句中的代码; (3) 如果catch子句中没有重新抛出异常,那么Java将执行try…catch…finally块后面的语句。如果在catch子句又重新
41
5.5 finally字句 抛出了异常,那么Java将这个异常抛出给方法的调用者;
(4) try块中产生了异常,而此异常在方法内没有被捕获。在这种情况下,Java将执行try块中的代码直到产生异常,然后跳过try块中的代码而转去执行finally子句中的代码,最后将异常抛出给方法的调用者。 例5.5 打开一个文件流,读入两个字符串,转化为整数,并求其和。 import java.io.*; class sum {public static void main(String args[]) { DataInputStream fis=null;
42
5.5 finally字句 catch(NumberFormatException e) try {
fis=new DataInputStream(new InputStream(“myfile.txt”)); //建立读入“myfile.txt”文件的输入流 String stra=fis.readln(); //读入一个字符串 int a=Integer.parseInt(stra); //把该字符串转化为整数 String strb=fis.readln(); int b=Integer.parseInt(strb); int c=a+b; System.out.println(c.toString()); //输出c } catch(FileNotFoundexception e) { System.out.printIn(e.toString()); } catch(IOException e) { System.out.println(e.toString()); } catch(NumberFormatException e) { System.out.println(e.toString()); }
43
5.5 finally字句 finally { if(fis= =null) {System.out.println(“DateInputStream not open!”) } //输入流没有打开 else { fis.close(); //关闭输入流 System.out.println(“Close DalaInStream!”); } } 在这个程序中,输入流的关闭是放在finally块中统一完成的。如果不使用finally语句,程序就要考虑在发生不同异常的情况下,文件是否能关闭。 考虑到在不同的可能出现的运行情况下,程序会从不同的地方退出try/catch结构,为了知道哪些地方要加上关闭的语句,
44
5.5 finally字句 就不得不分析在所有可能出现的情况下,文件输入流能否关闭:
(1) 文件正常运行,没有异常发生时,执行try块中全部语句,因而try块中要有关闭语句; (2) 产生文件没有找到异常,则输入流没有建立,也就不必关闭; (3) 产生读入字符引起的IO异常,进入相应的catch语句,需要在该catch块中关闭; (4) 产生字符串转化为整数时的类型不匹配异常,进入相应的catch语句,需要在该catch块中关闭。 根据这一分析,程序可能就要写成如下的形式: //不用finally语句的sum.java import java.io.*; class sum{ public static void main(String args[]) //方法main()没抛出异常
45
5.5 finally字句 {DataInputStream fis=null; try { //try体可能有抛出的异常或程序错
fis=new DataInputStream(new FileInputStream(“myfile.txt”)); //建立读入“myfile.txt”文件的输入流 String stra=fis.readLine(); //读入一个字符串, 可能抛出异常 int a=Integer.parseInt(stra);//把该字符串转化为整数 String strb=fis.readLine();//读入一个字符串, 可能抛出异常 int b =Integer.parseInt(strb); //把该字符串转化为整数 int c=a+b; System.out.println(c.toString()); //输出c fis.close(); } catch(FileNotFoundException e) { System.out.println(e.toString()); }
46
5.5 finally字句 catch(IOException e) {System.out.println(e.toString());
fis.close(); } catch(NumberFormatException e) {System.out.println(e.toString()); fis.close();} } 很明显,在程序中有三处地方要执行fis.close()语句,使程序代码重复,而且今后进行修改时也容易出错。所以用finally语句的一个好处,就是把方法中所有清除状态和关闭文件的语句放在一起,不但避免了代码重复,更减少了出现遗漏语句的现象,对程序将来的修改也较为集中和方便。
47
5.6正确地使用异常 由于异常使用起来非常方便,以至于在很多情况下可能会滥用异常。但是,使用异常处理会降低程序运行的速度,如果在程序中过多地使用异常处理,程序的执行速度会显著地降低。这里给出几点建议,来帮助掌握好使用异常处理的尺度。 (1) 在可以使用简单的测试就能完成的检查中,不要使用异常来代替它。例如: if (ins!=null) //使用ins引用对象 { … } (2) 不要过细地使用异常。最好不要到处使用异常,更不要在循环体内使用异常处理, 可以将它包裹在循环体外面. (3) 不要捕获了一个异常而又不对它做任何的处理。如下例所示:
48
5.6正确地使用异常 try { …… //正常执行的代码 } catch(Exception e) { }
(4) 将异常保留给方法的调用者并非不好的做法。 对于有些异常,将其交给方法的调用者去处理是一种更好的处理办法。
49
小结 异常处理把Java程序各种可能出现的错误都看作异常,集中起来统一处理。程序员只需要说明何处理可能的出现异常,如何处理即可。
throws抛出异常和方法说明联系在一起,是针对以下情况:调用的方法抛出了异常、检测到了错误并使用throw语句抛出异常、程序代码有错误从而异常。 try-catch异常处理机制。当try体中发生了一个异常,try-catch语句就会自动在try体后面的各个catch语句中,找出与该异常类相匹配的参数,就执行包含这一参数的catch语句中的java代码,执行完catch语句后,程序恢复执行,但不会回到异常发生处理继续执行,而是执行try-catch结构后面的代码。 finally语句为异常处理事件提供的一个清理机制。
50
习题 1.什么是异常?简述Java的异常处理机制。 2.系统定义的异常与用户自定义的异常有何不同?如何使用这两类异常?
3. 编写从键盘读入10个字符放入一个字符数组,并在屏幕上显示它们的程序,程序中处理数组越界异常。
51
6.1 java可重用类的结构 Java有一系列功能强大的可重用类, 功能相关的可重用类组织成包。可重用类的继承层次和包的组织呈树型结构。
52
6.1 java可重用类的结构 Java可重用类本书中主要涉及的有: 语言包 java.lang(lang意为language)
输入/输出包 java.io、 实用程序包 java.util(util意为utility) 小应用程序包 java.applet 图形用户接口包 java.swing 网络包 java.net 前三种包称为基础包,后三种包称为应用包。 图6-1 给出了Jave资源的层次结构
53
图6-1 Java工具包层次图 ….. ….. ….. ….. ….. Java.lang.Math Java Java.lang
Java.lang.System ….. Java.net Java.io.File Java.io ….. ….. Java.util ….. Java.applet ….. Java.swing 图 Java工具包层次图
54
Object类 public boolean equals(Object obj) 比较对象是否相等
protected Object clone()用来生成当前对象的拷贝,被 克隆的对象必须支持Cloneable public final Class getClass()用来生成当前对象所属类的信息
55
6.2 Java语言包(Java.lang) Java语言的核心部分是java. lang, 它定义了Java中的大多数基本的类。
下面介绍其中的类: object Class——为运行时搜集的信息 Math——提供数学常数及各种函数。
56
6.2 Java语言包(Java.lang) System——提供对操作系统的访问,包括默认的I/O流环境变量、自动垃圾收集、系统时间和系统属性; Runtime——提供了操作系统的访问:使用java.lang.System可以更容易地访问大多数Runtime方法;唯一的例外是exec方法,它开始一个新进程。 Thread——和java.lang.Runnable接口协同作用提供Java中的多线程的支持。 Throwable——它是Java中所有异常(Exception)的基类
57
6.2 Java语言包(Java.lang) 字符串类 数据类型类 Math类
58
数据类型类 数据类型类 基本数据类型类 Boolean boolean Character char Double double Float
Integer integer Long long
59
6.2.1 字符串类 1. String类 2. StringBuffer类 java.lang提供了两种字符串类:
字符串类 java.lang提供了两种字符串类: String类 StringBuffer类 1. String类 2. StringBuffer类
60
String类 String类可创建一个对象,用于代表一个字符串(不变的字符串),并定义了类似查找,比较和连接字符的操作。
String s=”Hello!”; public String(); public String(StringBuffer buffer) public String(String ss); public String(char value[]); public String(char value[],int offset,int count); public String(byte ascii[] ,int offset, int count) public String(byte ascii[]) 方法:
61
1. String类 String类提供了丰富的字符串操作方法,主要有: 字符串的比较:
public boolean equals(String s) public boolean equalsIgnoreCase(String s) 与字符串s比较相等否,相等返回true;反之,返回false public int compareTo(Object obj) public int compareTo(String s) public int compareToIgnoreCase(String s) 与字符串s比较字典顺序, 相等返回0; 当前串大于s返回1; 当前串小于s返回-1
62
1. String类 判断字符串的前缀和后缀 public boolean regionMatches
(int toffset,String Other,int offset,int len); 判断两个字符串的指定区域的字符子串是否相同 判断字符串的前缀和后缀 public boolean startsWith(String prefix) 如当前串以串prefix开始则返回true; 否则返回false public boolean endsWith(String suffix) 如当前串以串suffix结尾则返回true; 否则返回false
63
1. String类 public static String valueof(数据类型 data)
求字符串的长度 public int length() 字符串的连接 public String concat(String str) (注:使用“+”运算符更方便) 字符串的截取: public char charAt(int index):截取一个 public String substring(int beginindex,int endindex) 字符串的查找 public int indexOf(String str) 在当前字符串中寻找与str匹配的子串,返回首次匹配的起始下标 值,无匹配返回-1。 public int lastIndexOf(String str) public int lastIndexOf(String str,int fromIndex) 其它数据类型转换成字符串 public static String valueof(数据类型 data) 大小写转换 public String toLowertCase() public String toUpperCase() 拷贝到数组 public char[] toCharArray() 注意: String类的所有方法都不会改变String类对象本身的值!
64
2. StringBuffer类 StringBuffer类实现一种动态可变的字符串。 StringBuffer类提供三种创建方法:
public StringBuffer(); public StringBuffer(int length); public StringBuffer(String str);
65
2. StringBuffer类 StringBuffer类提供的方法主要用于把输入数据转换为String类。
public int length() 返回缓冲区的当前字符数。 public int capacity() 返回缓冲区的最大容量。 public synchronized StringBuffer append(type variable) public synchronized StringBuffer append(Char(char ch)) public synchronized StringBuffer insert(int offset,type variable) 把variable转换为字符串,然后插入到当前串由offset指定的位置
66
2 . StringBuffer类 例6.1 利用StringBuffer类将键盘输入的数据建立一个字符串实例。
public synchronized StringBuffer insert(int offset,char ch) 把字符ch插入到当前串由 offset指定的位置 public synchronized String toString() 把 StringBuffer 转换为字符串 String 例6.1 利用StringBuffer类将键盘输入的数据建立一个字符串实例。 import java.io.*; public class StringBufferToString {public static void main(String args[]) {char ch; try
67
2. StringBuffer类 {int length =20; //置StringBuffer的大小为20(书上有错)
StringBuffer strb=new StringBuffer(length); while ((ch=System.in.read())!=’\n’) { strb.append(ch) } String str=strb.toString(); // (书上这二句放后面, 错) System.out.println(str); } catch (IOException e) { }
68
6.2.2 数组 1 一维数组 2 多维数组 数组是相同类型的数据元素按顺序组成的一种复合数据类型 元素在数组中的相对位置由下标来指明。
数组 数组是相同类型的数据元素按顺序组成的一种复合数据类型 元素在数组中的相对位置由下标来指明。 数组中的每个元素通过数组名加下标进行引用。 在Java中,数组是一个类,所以要用new建立实例才可用。 数组分为一维数组和多维数组。 1 一维数组 2 多维数组
69
1. 一维数组 1) 一维数组的说明与构造 其格式如下: 类型 数组名[ ]; (或 类型 [ ]数组名;)
1. 一维数组 1) 一维数组的说明与构造 其格式如下: 类型 数组名[ ]; (或 类型 [ ]数组名;) 数组名 = new 类型[数组长度];
70
1. 一维数组 2) 数组的初始化 数组的初始化方式有两种: 一、在说明数组的同时进行初始化(称为静态初始化);
1. 一维数组 2) 数组的初始化 数组的初始化方式有两种: 一、在说明数组的同时进行初始化(称为静态初始化); 二、仅用new创建数组,让它取缺省值,到以后再为元素 赋值(称为动态初始化)。
71
1. 一维数组 例如: int a[ ]={1,2,3,4,5}; //静态初始化
1. 一维数组 例如: int a[ ]={1,2,3,4,5}; //静态初始化 int list[ ] = new int[3]; //动态初始化
72
1. 一维数组 3) 数组元素的使用 声明了一个数组,并用new语句为它分配了内存空间后,就可以在程序中像使用任何变量一样来使用数组元素,数组元素的标识方式为: 数组名[下标] 下标数据类型只能为byte,short,int, 而不能为long。
73
1. 一维数组 Java.util.Arrays System 封装了一些对数组整体进行操作的方法
74
2 . 多维数组 多维数组是通过对一维数组的嵌套声明来实现的。 1) 二维数组的说明与创建 二维数组说明的格式为:
2 . 多维数组 多维数组是通过对一维数组的嵌套声明来实现的。 1) 二维数组的说明与创建 二维数组说明的格式为: 类型 数组名[ ] [ ];(或 类型 [ ][ ] 数组名;) 此时还没有为数组元素分配内存空间,还需要用new关键字来创建数组,然后才可以使用该数组的每个元素。
75
2. 多维数组 a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2]
2. 多维数组 对二维数组来说,分配内存空间有下面几种方法。 (1)直接为每一维分配空间,如: int a[ ] [ ] = new int[2] [3]; a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2] (2)从最高维开始,分别为每一维分配空间,如:
76
2. 多维数组 b[0][0] b[0][1] b[0][2] b[1][0] b[1][1] b[1][2] b[1][3]
2. 多维数组 这说明,Java中并不要求构成多维数组的各个维数都相同。但在声明中第一维的维数一定要声明 int b[ ][ ] = new int[2] [ ]; b[0] = new int[3]; b[1] = new int[5]; 下图为该数组的示意图。 b[0][0] b[0][1] b[0][2] b[1][0] b[1][1] b[1][2] b[1][3] b[1][4]
77
2. 多维数组 2) 二维数组元素的初始化 (1) 在说明数组的同时进行初始化。 二维数组元素的初始化同一维数组一样有两种方式:
2. 多维数组 2) 二维数组元素的初始化 二维数组元素的初始化同一维数组一样有两种方式: (1) 在说明数组的同时进行初始化。 (2) 仅用new创建数组,让它取缺省值,到以后再为元素赋值(称为 动态初始化)。
78
2. 多维数组 例: int a[ ][ ] = { {1}, {2,3}, {4,5,6} }; 3)二维数组元素的引用
2. 多维数组 例: int a[ ][ ] = { {1}, {2,3}, {4,5,6} }; 3)二维数组元素的引用 对二维数组中每个元素,其引用方式为: 数组名 [下标1] [下标2] 其中下标1、下标2为非负的整型常数或表达式,如:a[2][3] 、cc[i+2][j*3 ](i,j为整型)等。同样,每一维的下标取值都从0开始。
79
Math类 java.lang.Math类是标准的数学类,封装了一些数学函数和常量。它的所有方法和变量也都是静态的。 1 三角函数 2 乘方 3 舍入 4 其他
80
1. 三角函数 (1)sin(double a) 返回弧度a的sin值 (2)cos(double a) 返回弧度a的cos值
下面的三个方法接受一个double类型的且以弧度为单位的角度值,并返回相应的运算结果,返回类型均为double型。 (1)sin(double a) 返回弧度a的sin值 (2)cos(double a) 返回弧度a的cos值 (3)tan(double a) 返回弧度a的tan值 下面的三个方法是反三角函数,返回类型均为double型。 (1)asin(double r) 返回 sin值为r的弧度 (2)acos(double r) 返回 cos值为r的弧度 (3)atan(double r) 返回 tan值为r的弧度 例: Math.sin(3.1416/6) 将返回 例: Math.cos(3.1416/4) 将返回 例: Math.asin(0.5) 将返回 (即π/6 )
81
2. 乘方 例: Math.pow (2.0, 3) 将返回 8.0 例: Math.sqrt (16) 将返回 4.0
(1) pow(double x, double y) 返回x的y次方。 (2) exp(double x) 返回ex (3) log(double x) 返回x的自然对数。 (4) sqrt(double x) 返回x的平方根。 (返回类型均为double型) 例: Math.pow (2.0, 3) 将返回 8.0 例: Math.sqrt (16) 将返回 4.0 注意:使用数学函数时,别忘加 “Math.”,即不要把“ Math.sqrt(16) ” 写成 “ sqrt(16) ”
82
3. 舍入 (1) ceil(double a) 返回大于或等于a的最小整数值。
(2) floor(double a)返回小于或等于a的最大整数值。 (3) rint(double a) 返回四舍五入后的整数值。 (上面三个方法的返回类型均为double型) (4) round(float a) 返回四舍五入后的整数值, 返回类型为int型。 (5) round(double a) 返回四舍五入后的整数值, 返回类型为long型。 例:Math.ceil(2.1) 将返回 Math.rint(2.1) 将返回2.0 Math.ceil(-2.1) 将返回 Math.round(2.1) 将返回2 Math.floor(2.1) 将返回 Math.round(2.5) 将返回3 Math.floor(-2.1) 将返回-3.0
83
4.其它 (1)abs(a) 返回a的绝对值 (2)max(a,b) 返回a和b的最大值 (3)min(a,b) 返回a和b的最小值
a可以是int、 long 、float、double型,返回类型与a的类型相同。 (2)max(a,b) 返回a和b的最大值 (3)min(a,b) 返回a和b的最小值 (2)、(3)中的a、b类型相同, 可以是int、 long 、float、double型,返回类型与a、b的类型相同。 (4) random() 返回一个0.0到1.0之间的随机数,返回类型为double型
84
6.3 常用容器数据类型 6.3.1 数组 6.3.2 向量类及其使用 6.3.3 哈希表类及其应用 6.3.4 栈类
6.3 常用容器数据类型 java.util包提供了许多实用的类,如:日期、向量、哈希表、锁和堆栈等。 6.3.1 数组 向量类及其使用 哈希表类及其应用 栈类 日期时间类()
85
java.util包的构成 java.util包由一些实用类组成的,有些类还是Java语言所不可缺少的。java.util包的大致层次结构如图6-4所示
86
图6-4 java.util 包层次结构 java.util.* 说明:
Dictionary是抽象类,Enumeration和Observer是接口,其余属于普通类; Hashtable除继承Dictionary类外,还是java.lang类库中Cloneable的一个实现; BitSet和Vector除继承了类Object外,同时也是java.lang.Cloneable的实现; BitSet是最终类,不能用以创建子类。
87
6.3.2 日期时间类 日期时间类是一个相对简单、但使用频繁的类,它提供了独立于具体系统的日期/时间的表示形式。
日期时间类 日期时间类是一个相对简单、但使用频繁的类,它提供了独立于具体系统的日期/时间的表示形式。 日期时间类的实例可通过如下几种方法予以创建: 1) public Date() 这个构造方法将把当前日期和时间保存于所创建的Date实例。 2) public Date(int year, int month, int date)
88
6.3.2 日期时间类 3) public Date(int year, int month, int date, int hours,
日期时间类 3) public Date(int year, int month, int date, int hours, int minutes) 4) public Date(int year, int month, int date, int hours, int minutes,int seconds) 下面是日期时间类的一些方法:
89
6.3.2 日期时间类 public int getYear(); 返回当前日期中的年份
日期时间类 public int getYear(); 返回当前日期中的年份 public int getMonth(); 返回当前日期中的月份 public int getDate(); 返回当前日期中的日(0-31) public int getDay(); 确认某天是星期几 public int getHours(); 返回当前日期中的小时数 public int getMinutes();返回当前日期中的分钟数 public int getSeconds();返回当前日期中的秒数 public boolean before(Date when);对日期实例所代表的时间和when进行比较.若比when早,返回true; 否则返回false public boolean after(Date when);对日期实例所代表的时间和when进行比较。若比 when晚,返回true;否则返回false public boolean equal(Object obj); 比较两个日期对象,若相等则返回true;否则返回false
90
日期时间类 public String toString(); 返回当前日期参数的字符串表示形式。注意:不同主机系统的日期表示形式不尽相同 日期时间类的使用非常简单, 只需要创建一个类实例不带任何参数, 即可以生成一代表当前日期的类。如下所示: Date today = new Date( ); System.out.println(today.toString( )); 或者也可用一更为简单的方式: System.out.println(today); 后一种方式中,println将自动调用toString方法,因而无需显式调用。
91
向量类(Vector)及其使用 1. 向量和数组的异同 2. 向量类的构造方法、属性和方法 4. 向量维护 5. 对象查找
92
1. 向量和数组的异同 向量(Vector)和数组存在许多相似之处,它们都是类,均可用以保存列表。 数组只能保存固定大小的列表,列表中元素的类型必须一致,必须一次申请所有的存储单元。如果事先无法确定列表内究竟要存放多少对象,Java的数组就无能为力了。 向量却提供了一种与 “动态数组” 相近的概念,它可以动态地增加它的列表长度,列表中元素的类型还可以不一致,但必须都是对象。 另外,向量提供了比数组更多的方法。 尽管向量与数组相比有许多重要的优点,但它也有一些不足之处,其中之一是它不能直接存储简单数据类型。
93
1. 向量和数组的异同 下列场合较适合于使用向量: 下列场合较适合于使用数组:
1) 如果需要频繁进行对象的插入和删除工作,或者需要处理的对象数目不定; 2) 列表成员全部都是对象(类型可不一致),或者可以用对象方便地表示; 3) 需要很快确定列表内是否存在某一特定对象,并且希望很快了解到对象的存放位置。 1) 所需处理的对象类型一致,数目固定或大致可以确定,尽管具体对象经常发生变化; 2) 所需处理的是简单数据类型。 由于向量只能存储对象,故如果需要把简单数据类型保存到向量,必须使用Java的数据类型类,因此,有些场合下使用数组要比使用向量方便一些。
94
2. 向量类的构造方法、属性和方法 向量容量、容量增量 向量容量——向量中可存放的元素个数
2. 向量类的构造方法、属性和方法 向量类共有3种形式的构造方法,如下所示: Vector(int capacity, int capacityIncrement); 用指定的向量容量及其增量参数,创建一个空向量 Vector(int capacity); 用给定的向量容量参数, 创建一空向量 Vector( ); 创建一空向量 向量容量、容量增量 向量容量——向量中可存放的元素个数 容量增量——规定了每当向量元素个数达到极限时,需一次性扩充的向量容量大小
95
2. 向量类的构造方法、属性和方法 “容量增量”参数说明 如果容量增量参数为0,则每次向量容量都将增加一倍大小。如果忽略这两个参数,这时Java将自动为维护向量的使用,包括必要时向量的增容等。 向量类提供了如下3个属性变量: protected int capacityIncrement; 当向量大小不足时,所用的增量大小 protected int elementCount; 向量的元素个数 protected Object elementData[ ];向量成员数据所用的缓冲
96
2. 向量类的构造方法、属性和方法 下面是其中一些主要的方法:
2. 向量类的构造方法、属性和方法 下面是其中一些主要的方法: public final synchronized void copyInto(Object anArray[]); 把向量元素拷贝到指定数组 public final synchronized void trimToSize(); 把向量容量调整到正好等于向量元素个数以压缩向量的存储 空间。这样,随后的插入操作将导致重新申请内存空间 public final synchronized void setSize(int newSize); 设置向量大小。如果向量被缩小,多余的元素将被截断;如果被放大,新增的向量元素将置为null public final int capacity() 返回向量容量 public final int size() 返回向量的元素个数,注意和capacity( )之间的区别
97
2. 向量类的构造方法、属性和方法 public final Boolean isEmpty()
2. 向量类的构造方法、属性和方法 public final Boolean isEmpty() 若向量不包括任何元素,返回true;否则返回false public final synchronized Enumeration elements() 返回向量元素所对应的枚举值,以便随后用Enumeration( )方 法获取该向量元素 public final boolean contains (Object elem) 若向量中包括了对象elem,返回true;否则返回false public final int indexOf (Object elem) 返回向量下标;若对象不存在,返回-1 public final synchronized int indexOf (Object elem, int index) 从指定位置(index)开始搜索向量,返回对象所对应的向量下 标值。若未找到对象,返回-1 public final int lastIndexOf (Object elem) 从向量末尾向前搜索向量,返回对象的下标值
98
2. 向量类的构造方法、属性和方法 public final synchronized int lastIndexOf(Object elem,int index) 从指定位置开始向前搜索向量,返回给定对象的下标值 public final synchronized Object elementAt(int index) 返回指定下标处的对象若下标值非法,抛出一 ArrayIndexOutOfBoundsException异常情况 public final synchronized Object fistElement() 返回向量的第一个元素。若向量为空,抛出一个 NoSuchElementException异常情况 public final synchronized Object lastElement() 返回向量的最后一个元素。若向量为空,抛出一
99
2. 向量类的构造方法、属性和方法 public final synchronized void setElementAt(Object obj, int index) 把给定对象存放到给定下标处,该下标处的原有对象丢失.若下标值非法,抛出异常情况ArrayIndexOutOfBoundsException public final synchronized void removeElementAt(int index) 删除给定下标处的向量元 素,后面元素前移一个位置。若下标值非法,抛出异常情况ArrayIndexOutOfBoundsException public final synchronized void insertElementAt(Object obj, int index) 把给定对象插入到指定下标处. 该下标之后的元素后移一个位置.若下标值非法,抛出异常ArrayIndexOutOfBoundsException
100
2. 向量类的构造方法、属性和方法 public final synchronized void addElement (Object obj) 把给定对象增加到向量末尾 public final synchronized boolean removeElement (Object obj ) 从向量中删除指定对象。若给定对象在向量中有多个,则只删除其第一个实例。若向量中没有这个对象,返回false public final synchronized void removeAllElements ( ) 删除向量中的所有对象。这时向量将变成空向量 public final synchronized String toString ( ) 把向量转换成字符串。请注意:这个方法实际上覆盖了Object类中的 toString()方法
101
3 . 建立向量实例 Vector theVector = new Vector();
一个向量在被创建后,将自行在系统内部维护一个专用数组,并在必要时对数组大小进行动态调整。比方说,如果插入一个向量元素时,向量的空间需求超过了这个内部数组的大小,向量将向系统申请一些新的内存空间。
102
4. 向量维护 例: 向量可用以保存任何类型的对象,同一个向量实例甚至还可以保存多种不同类型的对象。 增:
4. 向量维护 增: addElement( )方法把对象插入到向量末尾。 例: Vector theVector = new Vector( ); for( int i = 0; i<10; i++ ) { Integer newInteger = new Integer(i); theVector.addElement( newInteger ); } 向量可用以保存任何类型的对象,同一个向量实例甚至还可以保存多种不同类型的对象。
103
4. 增,改: 下面的例子是给向量交错插入一些浮点数和字符串。
4. 增,改: 下面的例子是给向量交错插入一些浮点数和字符串。 Vector theVector = new Vector( ); String testString; testString = “pai”; theVector.addElement( testString ); Float testFloat = new Float( 3.14 ); theVector.addElement( testFloat ); testString = “Faill”; theVector.addElement(testString); testFloat = new Float( 59 ); //注:书是多了’Float’ 向量:{“pai”, 3.14, “Faill”, 59} 增加向量元素的另一方式是通过insertElementAt( )方法。该方法把对象插入到向量的给定位置。
104
4. 向量维护 前两个方法在删除一个元素之后,后面的对象将前移一个位置。 删: 这时有3个方法可用:
4. 向量维护 删: 这时有3个方法可用: removeFlement(); 删除指定对象 removeElementAt(); 删除给定位置处的对象 removeAllElement(); 删除所有向量成员 前两个方法在删除一个元素之后,后面的对象将前移一个位置。 对于前面例子中介绍的向量,下面语句将删除其中的3.14和59,而不是3.14和“Faill”。 Float deleteFloat = new Float(3.14); theVector.removeElement(deleteFloat); theVector.removeElementAt(2);
105
5. 对象查找 对象查找中最常遇见的情况是给定一个下标值,希望由此确定该下标处的对象。这时可使用elementAt( )方法。
5. 对象查找 对象查找中最常遇见的情况是给定一个下标值,希望由此确定该下标处的对象。这时可使用elementAt( )方法。 对应前面的程序,下面这行程序返回一对象引用,该引用指向向量成员”pai” : Object tempObj = theVector.elementAt(0); 当需要确定向量中是否包括了某一确定的对象时, 可使用contains( )方法。 public final Boolean contains(Object elem); 这个方法返回一布尔值。若向量包含了对象elem, 返回true ,否则返回false。
106
5. 对象查找 利用下标进行访问 用下标来访问数组元素, 这是使用数组的最有效方法。向量成员也可用下标进行访问, 方法有:
5. 对象查找 利用下标进行访问 用下标来访问数组元素, 这是使用数组的最有效方法。向量成员也可用下标进行访问, 方法有: elementAt() 返回给定下标处的对象 indexOf() 从给定下标处往后搜索向量中是否包含 指定的的对象 lastIndexOf() 从给定下标处往前搜索向量中是否包含
107
5. 对象查找 indexOf() 和 lastIndexOf()方法的完整声明形式如下:
5. 对象查找 indexOf() 和 lastIndexOf()方法的完整声明形式如下: public final synchronized int indexOf (Object elem, int start_index ) public final synchronized int lastIndexOf 这两个方法均用以从给定下标开始搜索向量,确定向量中是否包含了指定的对象。如果是,则返回该对象的下标值,否则返回-1。
108
6.3.4 哈希表 (Hashtable)类及其应用 1. 哈希表类的构造方法、属性变量和成员方法 2. 哈希表的使用
哈希表是一种支持对表中元素进行快速检索的线性表 特征:表中元素的平均检索时间与表中的元素个数无关。 哈希表是利用“码值(关键字)—元素”形式的存储列表的元素 1. 哈希表类的构造方法、属性变量和成员方法 2. 哈希表的使用
109
1. 哈希表的构造方法、属性变量和成员方法 2)属性变量 哈希表类没有定义属性变量 1)构造方法
哈希表 (Hashtable)类共有三种形式的构造方法: public Hashtable(int initialCapacity,float loadFactor); 参数initialCapacity给定哈希表创建初始可容纳的元素数 量,loadFactor为装载因子, 取值0.0到1.0之间 public Hashtable(int initialCapacity); 参数initialCapacity给定哈希表创建初始可容纳的元素数, loadFactor为缺省值 public Hashtable(); 参数initialCapacity和loadFactor)为均为缺省值 2)属性变量 哈希表类没有定义属性变量
110
1. 哈希表的构造方法、属性变量和成员方法 3) 成员方法 哈希表类定义的主要方法如下:
1. 哈希表的构造方法、属性变量和成员方法 3) 成员方法 哈希表类定义的主要方法如下: public int size() 返回哈希表大小(即表中元素个数) public boolean isEmpty() 确认哈希表是否为空 public synchronized Enumeration keys() 返回哈希表内关键字枚举值 public synchronized Enumeration elememnts() 返回哈希表内元素的一个枚举值对象,随后用Emumeration类方法顺序获取对象 public synchronized boolean contains(Object value) 确认哈希表内是否包括了给定的对象,与containKey()类似 public synchronized boolean containsKey(Object key) 确认哈希表内是否包括了给定的关键字(注意,书是有错!) public synchronized Object get(Object key) 获取对应关键字的对象,如不存在返回null
111
1. 哈希表的构造方法、属性变量和成员方法 protected void rehash() 再哈希,扩充哈希表使之可以保存更多的元素。当哈希表达到饱和时,系统将自动调用此方法 public synchronized Object put(Object key,Object value) 用给定的关键字把对象保存到哈希表中。随后该对象即可通过同样的关键字由get方法获取。这里的关键字和元素均不可为空 public synchronized Object remove(Object key) 从哈希表中删除与给定关键字相对应的对象,如该对象不存在返回null public synchronized void clear() 从哈希表中删除所有对象,使其为空 public synchronized String toString() 把哈希表内容转换为一字符串,此方法复盖了Object类的toString()方法
112
2.哈希表的使用 哈希表创建与Java中其它对象一样需使用new操作。
例如:HashTable hash_1=new HashTable(); 为了把对象保存到哈希表,必须为每一个对象分配一关键字。关键字可以为任意对象,但必须实现了hashCode()和equals()方法。Java提供的类几乎都提供了这两个方法。 建好哈希表后,增操作: hash_1.put(“one”,new Integer(1)); hash_1.put(“two”,new Integer(2)); hash_1.put(“three”,new Integer(3));
113
2.哈希表的使用 删操作:remove()方法。 hash_1.remove(“two”);
如指定的关键字不存在,remove()返回null。 查找操作: get()和containsKey()可以查找关键字对应的对象,不存在返回null。 例如: Integer n=(Integer) hash_1.get(“three”); if (n!=null) System.out.println(“three=”+n); 如果查找的关键字不存在,get返回null。
114
6.3.5 栈类 Java 语言规范中,栈类是向量类的子类,它满足FIFO(先进后出)的要求。 栈类定义的主要方法如下:
栈类 Java 语言规范中,栈类是向量类的子类,它满足FIFO(先进后出)的要求。 栈类定义的主要方法如下: public Stack(); 栈类构造方法 public Object push (Object item) 把对象压入栈 public Object pop () 从栈顶弹出一个对象 public Object peek() 读栈顶一个对象,但不弹出 public boolean empty() 测试栈是否为空, 是则返回True, 否则返回False
115
6.4 输入输出包(java.io) 6.4.1 流(stream) 6.4.2 基本输入/输出流 6.4.3 File类
6.4.4 字符流文件 6.4.5 字节流文件 过滤流 文件拷贝实例
116
6.4.1 流(stream) 数据源 数据宿 程序
117
6.4.1 流(stream) 流及有关的流类 “流”可以被理解为一条“管道”。这条“管道”有两个端口:一端与数据源(当输入数据时)或数据宿(当输出数据时)相连,另一端与程序相连。
118
6.4.1 流(stream) 只要在程序和数据源/数据宿之间建立了流,用户就不需要再关心数据来自何方或送向何处,程序中输入/输出操作的复杂性就大大降低了。所有输入/输出操作都转换为对流的操作。
119
6.4.1 流(stream) 流的分类 根据流中数据传输的方向,流被分为输入流和输出流。
根据“管道”里流动的数据的类型, 流被分为字符流(Character Streams) 和字节流 (Byte Streams), 根据流的建立方式和工作原理,流分为节点流 (Node Streams) 与过滤流 (Filter Streams),节点流是直接建立在输入、输出媒 体之上的,而过滤流必须以某一个节点流作为流的来源 图6-7 为java 字节流输入输出接口、类的继承图。
121
基本输入输出流 1 InputStream类 2 OutputStream类 3 System.in和System.out对象
122
InputStream类 read的重载 InputStream类表示基本输入流,是字节流,它定义了一套所有输入流都需要用的方法:
public int read() throws IOException 从流中读取一个字节并将该字节作为整数返回,若没有数据则返回-1 public int read(byte b[]) throws IOException 从流中读取多个字节放到b中, 返回实际读取到的字节数 public int read(byte b[],int off,int len) throws IOException 从流中读取最多len字节的数据, 放到数组b的下标off开始的单元中,返回读取到的字节数 (注: 书上解释不正确) public long skip(long n) throws IOException 跳过流中指定的字节数
123
InputStream类 byte b[]=new byte[3]; System.in.read(b);
System.out.println( System.in.read() ); System.out.println( (int)System.in.read() ); System.out.println( (byte)System.in.read() ); System.out.println( (char)System.in.read() ); 输入aaaa,输出: 97 a byte b[]=new byte[3]; System.in.read(b); for (int i=0;i<3;i++) System.out.print(b[i]+" "); System.out.println(); String s=new String(b); System.out.print(s); 输入aaa,输出: aaa
124
1. InputStream类 public int available() throws IOException
返回当前流中可用的字节数 public void close() throws IOException 关闭当前流对象 public synchronized void mark(int readlimit) 在流中标记一个位置 public synchronized void reset() throws IOExeeption 返回流中标记过的位置 public boolean markSupported() 返回一个流是否支持标记和复位操作的布尔值
125
1. InputStream类 当程序中调用InputStream进行请求时,所调用的方法就处于等待状态,例如: try
{ int byte=System.in.read(); } catch(IOException e) { System.out.println(e.toString()); } 程序在运行到System.in.read()时,等待用户输入且直到用户输入一个回车键为止。 注意:InputStream类操作的是字节数据而不是字符。 ASCII码中字符和字节数据对应的都是8位数据, 而在Unicode字符集中,字符都被设置为16位数据,这样, 利用InputStream类来接收键盘字符将接收不到字符的高位信息!
126
2. OutputStream类 public abstract void write(int b) throws IOException
与InputStream类相对应的输出流是OutputStream,它具有所有输出流类的基本功能,同InputStream类相似,它具有以下相应的方法: public abstract void write(int b) throws IOException 向流中写一个字节 public void write(byte b[]) throws IOException 向流中写入一个字节数组 public void write(byte b[],int off,int len) throws IOException 从数组b的第off个位置开始写入len长度的数据 public void flush() throws IOException 清空流并强制将缓冲区中的所有数据写入到流中 public void close() throws IOException 关闭流对象
127
3. System.in和System.out对象
为了支持标准的输入输出设备,Java定义了两个流的对象,静态成员: System.in 从键盘中读入数据 System.out 将数据输出到显示屏。 它们是类变量(对象), 可直接使用。 例6.2 用System.out和System.in对象处理输入和输出 class MyClass{ public static void main(String[]args) { byte buffer[]=new byte[20]; System.out.println(“请在下面输入一行字符:”); try { System.in.read(buffer,0,20); } //System.in.read抛出异常
128
3. System.in和System.out对象
catch(Exception e) { //捕获异常并处理 System.out.println (“读取输入字符出错,错误信息为:+e.toString()); } System.out.println(“您刚才输入的一行字符为:”); String inputStr=new String(buffer,0); System.out.println(inputStr); 上面程序在执行到System.in语句时, 等待用户输入字符, 然后将输入的字符重新在显示器中输出。在接收用户输入数据时可能出错,因此还对System.in捕获异常,若出现异常则在显示器中将异常信息显示出来。例如,将try块内的语句改成“System.in.read(buffer,0,30);”,就将发生异常.
129
6.4.3 File类 文件 目录 路径 文件(file)是存储在辅助存储器中的一组相关信息的集合,它可以存放程序、文档、图片、声音或视频信息等。为了便于对文件管理, 系统允许用户给文件设置或取消有关的文件属性, 如只读属性、隐藏属性、存档属性、系统属性。 目录(directory)是一种特殊的文件,用以存放普通文件或其他的目录。磁盘格式化时,系统自动地为其创建一个目录(称为根目录)。用户可以根据需要在根目录中创建低一级的目录(称为子目录),子目录中还可以再创建下一级的子目录,从而形成树型目录结构,目录也可以设置相应的属性。 路径(path)是从盘符经过各级子目录到文件的目录序列。由于文件可以在不同的磁盘、不同的目录中,所以在存取文件时,必须指定文件的存放位置。
130
6.4.3 File类 缺省目录 相对路径 绝对路径 文件的存放位置通过路径来描述,路径的表示格式为:盘符\目录名\…\文件名,比如在C盘根目录下的子目录WINDOW下子目录JAVA中的文件myfile.java,应表示为 C:\WINDOW\JAVA\myfile.java 其中,C:为驱动器名,表示C盘,而\WINDOW\JAVA\表示myfile.java所存储的位置,其中第一个“\”表示根目录,其余的“\”为各子目录之间、最后一级子目录与文件名之间的分隔符。 在一个树型目录结构中,任一时刻,可以指定一个当前工作或操作的子目录,称其为当前目录(又叫缺省目录)。凡从根目录开始的路径叫做绝对路径,应以“\”开头;凡不从根目录开始而从当前目录开始的路径叫相对路径,应从当前目录的下级目录开始写起。
131
6.4.3 File类 例如,假使上述文件myfile.java完整的文件标识是C:\WINDOW\JAVA\myfile.java,如果当前磁盘是C盘,可写成\WINDOW\JAVA\myfile.java;如果当前目录是C:\WINDOW,可写成JAVA\myfile.java;如果当前目录是C:\WINDOW\JAVA,可改写成myfile.java。 java.io包中定义了一个File类来专门处理文件,并获取文件的有关信息。Java语言中通过File类来建立与磁盘文件的联系。File类用来获取或设置文件或目录的属性,但不支持从文件读取数据或者往文件里写数据。文件是许多程序的基本数据源和数据宿,是保存永久数据和共享信息的媒体。在Java中,目录也被当作文件,可以用list方法列出目录中的文件名。
132
6.4.3 File类 创建文件对象有三种构造方法,这里引用三个例子分别创建了三个文件对象:file1、file2、file3,它们都指向文件“c:\cgi-bin\demo.java”。 File类的功能十分强大,它可以访问指定文件的所有属性,包括文件名称、文件长度、文件的最后修改时间等,同时还可以利用File类来建立文件对象、删除文件和改变文件名称等。 File类具有下面三种构造函数: File (String path); File (String path,String name); File (String dir,String name); 其中参数如下所示: String path——指定的路径; String name——执行的文件名; String dir——执行的目录;
133
6.4.3 File类 File类的有关方法: public String getName() 得到文件名
public String getPath() 返回文件路径 public String getAbsolutePath() 返回文件绝对路径 public String getCanonicalPath() throws IOException 返回文件的规范路径 public String getParent() 返回文件的父目录 public boolean exists() 判断文件是否存在 public boolean canWrite() 判断文件是否可写 public boolean canRead() 判断文件是否可读 public boolean isFile() 判断对象是否是文件 public boolean isDirectory() 判断对象是否是目录
134
6.4.3 File类 public native boolean isAbsolute() 如果文件名为绝对名则返回真
public long lastModified() 返回文件最后修改日期 public long length() 返回文件长度 public boolean mkdir() 创建目录 public boolean rename To(File dest) 重命名文件 public boolean mkdirs() 创建目录及子目录 public String[] list() 列出目录下的所有文件和目录 public String[] list(FilenameFilter filter) 列出目录下的指定文件 public boolean delete() 删除文件对象 public int hashCode() 为文件创建散列代码 public boolean equals(Object obj) 判断是否同对象obj相等 public String toString() 返回文件对象的字符串描述
135
6.4.3 File类 从上面方法中可以看出,File类不仅仅是对现有目录路径、文件和文件组的一个表示,它还可以利用File对象直接新建一个文件,甚至创建一个完整的目录路径(如果它还不存在的话);同时我们还可以利用该对象了解文件(文件夹)的属性(包括长度、上一次修改日期、读/写属性等),检查一个File对象到底是一个文件还是目录,以及删除一个文件对象等操作。 如果File对象是一个目录,可以调用其list方法列出File对象中包含的完整列表(包含File对象的文件夹和文件),若要对这个文件列表作出某种选择,就需要使用一个“目录过滤器”(也是一种“文件过滤器”),该类的作用就是按一定条件选择File对象。
136
6.4.3 File类 例. 文件过滤器 //源程序清单6.3 import java.io.*;
public interface FilenameFilter // 文件过滤器接口 { boolean accept(File dir,String name); } //只有一个抽象方法,无方法体 public class DirFilter implements FilenameFilter { //DirFilter实现上述接口来对文件过滤 String extn; //文件过滤要求,文件名包含extn public DirFilter(String extn) //构造方法 { this.extn=extn; }
137
6.4.3 File类 public boolean accept(File dir,String name)
{boolean isAccept; String f=(new File(dir,name)).getName(); if(f.indexOf(extn)==-1) //文件名不包含extn isAccept=false; else //文件名包含extn isAccept=true; return isAccept; } 下面的例6.4利用上述过滤器找出当前目录下面指定类型(*.java)的文件。
138
6.4.3 File类 //源程序清单6.4 import java.io.*; public class DirList {
public static void main(String[] args) { try { File file=new File(“.“); //当前路径文件对象 String[] list=file.list(new DirFilter(“*.java”)); for(int i=0;i<list.length;i++) System.out.println(list[i]); } catch(Exception e) { System.out.println(e.toString()); }
139
6.4.4 字符流文件 1 文件输出流(FileWriter) 2 文件输入流(FileReader)
字符流文件 上节介绍了如何创建一个文件,但是我们更需要了解如何往文件里写数据或读出文件中的内容。文件的读写是通过文件输入流、文件输出流来实现的。 按数据交换的单位不同,文件流可分为字符流、字节流两种,这一节中介绍以字符为单位进行文件访问,以字节为单位的方式在下一节介绍,读写的方式都是顺序方式。 1 文件输出流(FileWriter) 2 文件输入流(FileReader)
140
1. 文件输出流(FileWriter) FileWriter类可以在一指定的文件上建立一个文件输出流,也可以建立一个文件同时实例化为文件输出流。流提供了将数据写到文件中的方法。如果用FileWrite来打开一个只读文件会产生IOExcption异常。 FileWriter类有两种构造方法: 构造方法一: File f=new File(“d:\\t1.txt”); //建立文件 FileWriter f1=new FileWriter(f); //建立文件输出流 构造方法二: (建立文件同时实例化为文件输出流) FileWriter f2=new FileWriter(“d:\\t1.txt”); 第一种方法是先建立一个文件对象f,然后再建立一个输入
141
1. 文件输出流(FileWriter) 注意:写完后一定要关闭输出流,数据才真正地写到了文件中!
流f1,并使输入流f1和文件f相连接。这种情况下,可以通 过对象f对该文件作进一步的分析, 比如, 显示文件的属性、 大小等。第二种方法就是将第一种方法的二步合成一步,相对来说更方便一些,但不能做文件分析等其它工作。 FileWriter类的最重要的方法是write()与close(): (1) write(char c) 将一个字符写到文件的末尾 (2) write(char b[ ]) 将一个字符数组写到文件的末尾 (3) close() 关闭输出流 注意:写完后一定要关闭输出流,数据才真正地写到了文件中!
142
1. 文件输出流 例. 在d盘上建立一个名为myfile.txt的文件,并写入两串字符。 import java.io.*;
public class FileOutput {public static void main(String[]args)throws Exception {File f = new File("d:\\myfiel.txt"); FileWriter f1 = new FileWriter(f); f1.write("abcdefghij"); f1.write("xyz"); f1.close(); }
143
2. 文件输入流(FileReader) FileReader类可以在一指定的文件上实例化一个文件输入流, FileReader类流提供了从文件中读取一个字符或者一组字符方法。FileReader类的构造方法都有可能出现FileNotFoundExcption异常。 构造方法一: File f=new File(“d:\\t1.txt”); FileReader f1=new FileReader(f); 构造方法二: FileReader f2=new FileReader(“d:\\t1.txt”); 这两种建立输入流的方法与前面建立输出流的两种方法意义完全类似。
144
2. 文件输入流(FileReader) FileReader类的最重要的方法是read()与close():
(2) read(char b[ ]) 读入字符放到字符数组b中并返回实际读入的字符数。如果所定义的字符数组容量小于获得的字符数,则运行时将产生一个IOException例外情况。 (3) read(char b[ ],int off,int len) 读入len个字符放到数组b下标off开始的位置中,并返回实际读入的字符数 (4) close() 关闭输入流
145
2. 文件输入流 import java.io.*; public class FileInput
例. 将d盘上名为myfile.txt的文件的内容输出到屏幕。 import java.io.*; public class FileInput {public static void main(String[]args)throws Exception {File f = new File("d:\\myfiel.txt"); FileReader f1 = new FileReader(f); char a[]=new char[(int)f.length()]; f1.read(a); System.out.println(a); f1.close(); }
146
字符文件输入/输出方法小结: 要建立(或打开)一个文件并对它进行输入、输出,需要如下几步: (1) 用File类建立(或打开)一个文件; (2) 用FileWriter(FileReader)类建立输出(输入)流; (3) 调用write(read)进行输出(输入) ; (4) 关闭输出(输入)流。
147
6.4.5 字节流文件 1 FileInputStream 2 FileOutputStream
字节流文件 平常所使用的文件中,有很多是二进制文件,它们以字节作为数据处理单位。对这些文件就要使用字节流来读写了,其实字符文件也可以用字节流来进行读写。 FileInputStream和FileOutputStream分别完成字节流文件的读写。 1 FileInputStream 2 FileOutputStream
148
1. FileInputStream FileInputStream类方法: int available() 返回可读入的字节数
void close() 关闭输入流,并释放任何与该流有关的资源 protected void finalize() 当读到无用信息时,关闭该流 FileDescriptor getFD() 返回与该流有关的文件描述符 (即文件的完整路径) int read() 从输入流中读取一个字节的数据 int read(byte[]b) 将数据读入到一个字节数组中 int read(byte[]b,int off,int len) 读入len个字节数据放到数组b的off开始的位置中 long skip(long n) 跳过输入流上的n个字节
149
2. FileOutputStream FileOutputStream类方法:
void close() 关闭输出流,并释放任何该流有关的资源 protected void finalize() 当写到无用信息时,关闭该流 File Descriptor getFD () 返回与该流有关的文件描述符 (即文件的完整路径) void write(int b) 将一个字节数据写到输出流中 void write(byte[ ]b) 将字节数组中的数据写到输出流中 long skip(long n) 跳过输出流上的n个字节
150
过滤流 过滤流必须建立在节点流之上,对节点流中的数据进行某些加工、处理,并提供一些友好的方法供用户进行输入、输出操作以及流控制。例如,BufferedInputStream可以对任何种类的输入流进行带缓冲区的封装以达到性能的改善(可减少程序I/O操作次数,提高程序执行效率)。Jave利用过滤流可以在读/写数据的同时对数据进行处理。 使用过滤流时要注意: 必须将过滤流和某个输入流或输出流(节点流)连接。而在程序设计中,连接是通过在过滤流的构造方法中指定入口参数——节点流来实现的。如: FileInputStream in=new FileInputStream(“text”); BufferedInputStream bufin=new BufferedInputStream(in); 实现了过滤流bufin和文件输入流in连接。
151
6.4.6 过滤流 BufferedInputStream BufferedOutputStream
过滤流 BufferedInputStream BufferedOutputStream DataInputStream和DataOutputStream ObjectInputStream和ObjectOutputStream
152
1. BufferedInputStream 该类有两个构造方法:
对I/O进行缓冲是一种常见的性能优化方法。Jave的BufferedInputStream类可以对任何的InputStream流进行带缓冲的封装以达到性能的改善。该类在已定义输入流上再定一个具有缓冲的输入流,可以从此流中成批地读取字符而不会每次都引起直接对数据源的读操作。数据输入时,首先被放入缓冲区,随后的读操作就是对缓冲区中的内容进行访问。 该类有两个构造方法: 1)public BufferedInputStream(InputStream in); 2)public BufferedInputStream(InputStream in,int size);
153
1. BufferedInputStream 两种构造方法都有是为某种输入流in 创建一个缓冲流 方法一 方法二 创建的缓冲大小为
缺省值(32bytes) 用户指定缓冲区大小 对方法二,在性能优化时,通常都把size的值设定为内存页大小或I/O块大小的整数倍。在I/O量不大时,该类所起作用不是很明显,但当程序I/O量很大,且对程序效率要求很高时,使用该类就能大大提高程序的效率。 对输入流进行缓冲可以实现部分字符重复使用。除了InputStream中常用的read和skip方法, BufferedInputStream还支持mark和reset方法。 注意mark只能严格限制在建立的缓冲区内。
154
2. BufferedOutputStream
BufferedOutputStream类在已定义节点输出流上再定义一具有缓冲功能的输出流。用户可以向流中写字符而不会每次都引起直接对数据宿的写操作,只有在缓冲区已满或清空流(flush)时,数据才输出到数据宿上。在Java中使用输出缓冲是为了提高性能。 该类有两个构造方法: 1)public BufferedOutputStream(OutputStream out); 2)public BufferedInOutputStream(OutputStream out, int size);
155
3. DataInputStream和DataOutputStream
DataInputStream用来从一种已定义的节点输入流中读取Jave基本数据类型的数据,如布尔型数、整型数、浮点数等,然后再生成一个数据输入流。 DataOutputStream用来将Jave基本数据类型数据写到一个数据输出流中。 这两个类都是在某节点流上再定义一个数据输入(输出)流,通过它们,用户可以更方便地按照Jave原始数据类型来读(写)数据。
156
3. DataInputStream和DataOutputStream
构造方法: 1)pubilc DataInputStream(InputStream in); 创建一新的DataInputStream,该流从输入流in读取数据 2)pubilc DataOutputStream(OutputStream out); 在输出流out上创建一个新的DataOutputStream,使DataOutputStream的输出数据能够输出到输出流out中 例如,建立基于标准输入的输入流的语句可如下: DataInputStream In=new DataInputStream(System.in);
157
3. DataInputStream和DataOutputStream
成员方法: readBoolean()、writeBoolean() 读写布尔型数据 readByte()、writeByte() 读写字节数据readChar()、writeChar() 读写字符数据 readLine()、writeLine() 读写整行数据 例如,要从键盘输入一行字符,语句可如下: DataInputStream In=new DataInputStream(System.in); String stra=In.readLine();
158
3. DataInputStream和DataOutputStream
例. 建立基于标准输入的过滤流并进行输入 import java.io.*; public class DataInput {public static void main(String[]args)throws Exception { int a; double b,c; String str; DataInputStream In=new DataInputStream(System.in); //建立基于标准输入的过滤流 str=In.readLine(); //读入一个字符串 a=Integer.parseInt(str); //把字符串转化为整数 b=Double.parseDouble(str); //把字符串转化为实数 c=a+b; System.out.println(c); }}
159
4. ObjectInputStream和ObjectOutputStream
例6.5 把Hashtable中存放的信息输出到磁盘文件中,并再从中读进Hashtable. packege ObjectIO; import java.io.*; import java.util.Hashtable; public class ObjectIOClass { public static void main(String args[]) throws Exception {Hashtable ht=new Hashtable(); //建立一个Hashtable对象
160
4. ObjectInputStream和ObjectOutputStream
DataInputStream dis=new DataInputStream(System.in); //建立DataInputStream对象,并且与标准输入对象连接 String st_no=dis.readLine();//从标准输入读一行存入st_no String st_rec=dis.readLine();//从标准输入读一行存入st_rec ht.put(st_no,st_rec); //st_no作关键字,st_rec为Hashtable保存的对象,存入ht System.out.println(ht); String st_no1=dis.readLine();//从标准输入读一行存入st_no1 if (ht.containsKey(st_no1)) //如Hashtable对象中有关键字st_no1,输出对应的对象 System.out.println(ht.get(st_no1)); else System.out.println("error");
161
4. ObjectInputStream和ObjectOutputStream
ObjectReadWrite my_object=new ObjectReadWrite(); //建立文件对象 my_object.write(ht); //如ht对象输出到输出源 my_object.read(); //从输入源读入对象 } public class ObjectReadWrite { static File object_file=new File("d:\\","data"); public static void write(Hashtable ht ) { try{ //建FileOutputStream对象,并与文件对象object_file连接 FileOutputStream fos=new FileOutputStream(object_file); //建立ObjectOutputStream对象,并与文件对象fos连接
162
4. ObjectInputStream和ObjectOutputStream
ObjectOutputStream oos=new ObjectOutputStream(fos); oos.writeObject(ht); //Hashtable对象内容写入输出文件中 //o1.flush(); oos.close(); } catch(Exception e){ }; public static void read() { //从对象输入文件中读对象 try { //建ObjectOutputStream对象,并与文件对象object_file连接
163
4. ObjectInputStream和ObjectOutputStream
ObjectInputStream ois=new ObjectInputStream ( new FileInputStream(object_file )); Hashtable ht1=(Hashtable)ois.readObject(); //从输入源读入对象 System.out.println(ht1); //标准输出ht1 } catch(Exception e){ e.printStackTrace(); }
164
6.4.7 文件拷贝实例 1 创建项目并设计主界面 2 获取、浏览文件 3 文件拷贝
文件拷贝实例 下面将通过一个文件或文件夹拷贝的实例来说明文件读写的过程。例6.5 用户在主窗口的源文件栏中输入或点击“浏览”按钮,在弹出的对话框中选择需要拷贝的源文件或文件夹,再在目标文件栏中选择目标文件或文件夹(允许不存在,系统将自动创建)。点击“复制”按钮进行拷贝,同时在右面的列表框中列出当前正在拷贝的文件名。应用程序执行界面如图6-7所示。下面将具体分步实现这个过程。 1 创建项目并设计主界面 2 获取、浏览文件 3 文件拷贝
165
1. 创建项目并设计主界面 //源程序清单6.5-1 package CopyFile; import java.awt.*;
打开Jbuilder,选择菜单“File→New…”,在新建向导中分别创建工程coptyFile.jpr和主窗体类MainFrame.java,并进入该窗口的design视图,加入如图6-5所示的各个组件,在design视图中双击四个按钮产生它们的点击事件。 //源程序清单6.5-1 package CopyFile; import java.awt.*; import java.awt.event.*; import borland.jbcl.layout.*; import borland.jblcl.control.*; public class MainFrame extends Frame { TextField textFieldl= new TextField(); Button button1 =new Button(); Label labe11 =new Label();
166
1. 创建项目并设计主界面 Label labe12 =new Label();
TextField textField2 =new TextField(); Button button2= new Button(); Button button3= new Button(); Button button4= new Button(); Label labe13 =new Label(); Panel Pane11 =new Panel(); PaneLayout paneLayout1=new PaneLayout(); PaneLayout paneLayout2=new PaneLayout(); GroupBox groupBox1=new PaneLayout(); List list1 =new List(); PaneLayout paneLayout3=new PaneLayout(); public MainFrame() { try{
167
1. 创建项目并设计主界面 jbInit(); } catch(Exception e) { e.printStackTrace();
private void jbInit() throws Exception { this.setSize(new Dimension(454,154)); this.setTitle(″拷贝文件″); this.setBackground(new Color(192,192,192); button.setLabel(″浏览″…); button1.addActionListener(new MainFrane_button1_actionAdapter(this));
168
1. 创建项目并设计主界面 //MainFrane_button1_actionAdapter由Jbuild生成
//按钮的监听器接口类 //MainFrane_button1_actionAdapter由Jbuild生成 labell.setAlignment(2); labell.setText(″源文件:″); labell2.setText(″目的文件″); button2.setLabel(″复制″); button2.addActionListener(new MainFrame_button2_actionAdapter(this)); //按钮的监听器接口类//MainFrane_button2_actionAdapter由Jbuild生成 button3.setLabel(″退出″); button4.addAactionListener(new MainFrame_button4_actionAdapter(this));
169
1. 创建项目并设计主界面 //按钮的监听器接口类MainFrane_button4_actionAdapter由Jbuild生成
button3.addAactionListener(new MainFrame_button3_actionAdapter(this)); //按钮的监听器接口类MainFrane_button3_actionAdapter由Jbuild生成 this.setLayout(paneLayout1); this.add(panel.new PaneConstraints (“panell”,”panell”,PaneConstraints.ROOT,0,5f); panel1.add(groupBox1,new PanConstraints (“groupBox1”,”groupBox1”,PaneConstraints.ROOT,1.of)); groupBox1.add(list1. new PaneConstraints (“listl”, “listl”,PaneConstraints.ROOT, I.of));
170
1. 创建项目并设计主界面 this.add(labell,new PanConstraints (“lable3”,
“panell”,PaneConstraints.LEET, f); this.add(labell. new PaneConstraints(“labell,“labell3”, PaneConstraints,BOTTOM, f) this.add(label2,new PaneConstraints(“label2”, “labell”,PaneConstraints,BOTTOM, f)); this.add(textField,new PaneConstraints(“textField”, “labell”,PaneConstraints.RIGHT, f)); this.add(button1,new PaneConstraints(“button2”, “label2”,PaneConstraints,BOTTOM, f)); this.add(button4,new PaneConstraints(“textField2”, “label2”,PaneConstraints.RIGHT, f)); this.add(button4,new PaneConstraints(“button4”,“
171
1. 创建项目并设计主界面 textField2”,PaneConstraints.RIGHT,0.3442623f));
this.add(button3.new PaneConstrains(“button3”, “button2”,PaneConstraints.RIGHT, f)); } public static void main(String[] args) { Main Frame frame=new MainFrame(); frame.setLocation(200,200); frame.setSize(450,150); frame.show(); void buttonl_actionPewrformed(ActionEvent e) {
172
1. 创建项目并设计主界面 void button2_actionPerformed(ActionEvent e) { }
上面程序所生成的四个按钮的监听器接口类由Jbuilder将其添加到MainFrame.java类的后面。 例6.6 源程序清单第2部分 class MainFrame_buttonl_actionAdapter implements java.awt.event.ActionListener { MainFrame adapter;
173
1. 创建项目并设计主界面 {this.adaptee=adaptee; }
MainFrame_buttonl_actionAdapter(MainFrame adaptee) { this.adaptee=adaptee; } MainFrame_butto1_actionAdapter(MainFrame adaptee) {this.adaptee=adaptee; } class MainFrame_button2_actionAdapter implements java.awt.event.ActionListener {MainFrame adaptee; MainFrame_butto2_actionAdapter(MainFrame adaptee) public void actionPerformed(ActionEvent e) {adaptee.button2_actionPerformed(e); } }
174
1. 创建项目并设计主界面 class MainFrame_button3_actionAdapter
implements java.awt.event.AactionListener { MainFrame adaptee; MainFrame_button3_actionAdapter(MainFrame adaptee) { this.adaptee=adaptee; } public void actionPerformed(ActionEvent e) { adaptee.button3_actionPerformed(e); } }
175
1. 创建项目并设计主界面 class MainFrame_button4_actionAdapter
implements java.awt.event.ActionListener { MainFrame adaptee; MainFrame_button4_actionAdapter(MainFrame adaptee) { this.adaptee =adaptee; } public void actionPerformed(ActionEvent e) { adaptee.button4_actionPerformed(e); } }
176
2. 获取浏览文件 我们可以调用系统的Filer组件来实现对系统文件夹的选取。Filer组件只作为一个对话框来显示打开或保存一个文件,用户可以通过对话框选择一个文件来打开或者是保存,而该组件用来打开或保存一个文件可以通过设置其mode属性来决定. 构造函数有四种方式: public Filer() 直接实例化一个对象,其它的属性以后再进行设置; public Filer(java.awt.Frame frame) 创建一个以frame为父窗体的对象; public Filer(java.awt.Frame frame,String title) 创建一个以frame为父窗口,以title为标题的对象; public Filer(java.awt.Frame.String title,int mode) 创建一个以frame为父窗口,以title为标题,类型为mode的对象,mode有两种取值,即: Filer.load——打开一个文件 Filer.save——保存一个文件
177
2. 获取浏览文件 实例化Filer对象后,可以通过调用其适当的方法来得到其需要打开或保存的文件目录.
2. 获取浏览文件 实例化Filer对象后,可以通过调用其适当的方法来得到其需要打开或保存的文件目录. Filer具有很多方法可以实现对Filer组件的控制: public String getDirectory() 返回选择后的文件目录 public void setDirectory(java.lang.String dir) 设置文件目录 public String getFile() 返回选定后的文件名 public void setFile(java.lang.String file) 设置文件名 public Frame getFrame() 得到父窗体对象 public void setFrame(java.awt.Frame frame) 设置父窗体对象
178
2. 获取浏览文件 public int getMode(int m) 设置打开保存方式
2. 获取浏览文件 public int getMode(int m) 设置打开保存方式 public String getTITLE() 得到标题 public void setTitle(java.lang.String title) 设置标题 public boolean isVisible() 返回是否可见 public void setVisible(boolean visible)设置是否可见 public void show() 显示组件 在MainFram类中添加两个Filer组件,并实现两个浏览按钮,将用户选择的打开(源)文件和保存(目的)文件路径显示在文本框中,实例化Filer组件,具体代码如下所示: Filer filer1=new Filer(this,this,”选择源文件”,Filer.load); Filer filer2=new Filer(this,this,”选择目的文件”,Filer.save);
179
2. 获取浏览文件 同时添加两个按钮的点击事件,最后得到MainFrame类。(粗体为所添加的代码) //源代码清单6-5-2
2. 获取浏览文件 同时添加两个按钮的点击事件,最后得到MainFrame类。(粗体为所添加的代码) //源代码清单6-5-2 import java.awt.*; import java.awt.event.*; import borland.jbcl.layout.*; import borland.jbcl.control.*; import java.io.*; import java.util.*; public class MainFrame extends Frame {TextField textField1 =new TextField(); Button button1=new Button(); Label labe11=new Label();
180
2. 获取浏览文件 Label labe12=new Label();
2. 获取浏览文件 Label labe12=new Label(); TextField textField2=new TextField(); Button button2 =new Button(); Button button3 =new Button(); Filer filer1 =new Filer(this,this,″选择源文件″,Filer.LOAD); Filer filer2 =new Filer(this,this,″选择目的文件″,Filer.SAVE); Button button4= new Button(); Label labe13 =new Label(); Panel pane11 =new Panel(); PaneLayout paneLayout1=new PaneLayout(); PaneLayout paneLayout2=new PaneLayout(); GroupBox groupBox1=new GroupBox();
181
2. 获取浏览文件 List list1=new List();
2. 获取浏览文件 List list1=new List(); PaneLayout paneLayout3=new PaneLayout(); Public MainFrame() { try { jbInit(); } catch(Exception e) { e.printStackTrace(); private void jbInit() throws Exception { this.setSize(new Dimension(454,154)); this.setBackground(new Color(192,192,192)); button1.setLabel(″浏览″...″);
182
2. 获取浏览文件 button1.addActionListener(
2. 获取浏览文件 button1.addActionListener( new MainFrame_button1_actionAdapter(this)); labell.setAlignmetnt(2); labell.setText(″源文件:″); labe12.setAlignement(2); label2.setText(″目的文件″); button2.setLabel(″复制″); button3.addActionListener( new MainFrame_button2_actionAdapter(this)); button3.setLabel(″退出″); button3.addAactionListener( new MainFrame_button3_actionAdapter(this));
183
2. 获取浏览文件 button3.setLabel(″浏览″...); button4.addActionListerer(
2. 获取浏览文件 button3.setLabel(″浏览″...); button4.addActionListerer( new MainFrame_button3_actionAdapter(this)); label3.setText(“请输入或选择源文件(夹)和目标文件(夹):”); groupBox1.setLayout(panLayout3); groupBox1.setLablel(″下载队列″); this.setLayout(paneLayoutl); this.add(pane11,new PaneConstraints (“panell”,“panell”,PaneConstraints.ROOT,0.51)); pane11.add(groupBox1.new PaneConstraints (“groupBox1”,“groupBox1”,PaneConstraints.ROOT,1.0f)); groupBox1.add(list1,new PaneConstraints (“list1”,”list1”,PaneConstraints.ROOT, 1.0f)); this.add(labe13,new PaneConstraints
184
2. 获取浏览文件 (“label3”,“panell”,PaneConstraints.LEFT,0.6300448f);
2. 获取浏览文件 (“label3”,“panell”,PaneConstraints.LEFT, f); this.add(labe11,new PaneConstraints(“labe11”,“labe13”, PaneConstraints.BOTTOM, f); this.add(label2,new PaneConstraints(“labe12”, “label11”,PaneConstraints.BOTTOM, f); this.add(textField1,new PaneConstraints (“textField1”,PaneConstrains.RIGHT, f); this.add(button1,new PaneConstraints(“button1”, “textField1”,PaneConstraints,RIGHT, f); this.add(textField2,new PaneConstraints(“textField2”, “label2,PaneConstraints.RIGHT, f); this.add(button4,newPaneConstraints(“button4”, “textField2”,PaneConstraints.RIGHT, f); this.add(button3,new PaneConstraints(“button3”, “buttonon2”,PaneConstraints.RIGHT, f); }
185
2. 获取浏览文件 public static void main(String[]args) {
2. 获取浏览文件 public static void main(String[]args) { MainFrame frame=new MainFrame(); Frame.setLocation(200,200); Frame.setSize(450,150); Frame.show(); } void button1_actionPerformed(ActionEvent e) { //加下划线为所添加的代码 filer.show(); String dir=filer1.getDirectory(); String file=filer1.getFile(); if (dir.equals(″null″)&&file.equals(“null”)) return; textField1.setText(dir+file);
186
2. 获取浏览文件 void button2_actionPerformed(ActionEvent e) {
2. 获取浏览文件 void button2_actionPerformed(ActionEvent e) { String sourceName=textField1.getText(); String desName=textField2.getText(); if(sourceName.equals(“”‖desName.equals(“”))retrun; pCopyFile=new PrepareCopyFile(); try{ pCopyFile.CopyFile(sourceName,desName); } catch(Exception ee){} } void button3_actionPerformed(ActionEvent e) { MessageDialog mdlg=new MessageDialog (this, “警告”,”确定要退出吗?”,6);
187
2. 获取浏览文件 mdlg.setSize(150.80); mdlg.show();
2. 获取浏览文件 mdlg.setSize(150.80); mdlg.show(); if(mdlg.gteResult()==MessageDialog.NO) retrun; System.exit(0); } void button4_actionPerformed(ActionEvent e) { filer2.show(); String dir=filer2.getDirectory(); String file=filer2.getFile(); if(dir.eqals(“null”)&&file.equals(“null”)) reurn; textField2.setText(dir+file);
188
3. 文件拷贝 在拷贝工作开始之前,还需要进行一些准备工作,首先就是实现向列表框中添加新拷贝的文件和删除已经拷贝完成的文件。
3. 文件拷贝 在拷贝工作开始之前,还需要进行一些准备工作,首先就是实现向列表框中添加新拷贝的文件和删除已经拷贝完成的文件。 //源代码清单6-5-3 void addCopyingFile(String sname) { File file=new File(sname); String sfilename=file.getName(); List,addItem(sfilename); } viod removeCopyingFile(String sname) { List,remove(sfilename);
189
3. 文件拷贝 然后完成拷贝按钮和退出按钮的事件。拷贝按钮事件的具体代码如下所示:
3. 文件拷贝 然后完成拷贝按钮和退出按钮的事件。拷贝按钮事件的具体代码如下所示: String sourceName=textFieldl.getText(); String.desName=textField2.getText(); if(sourceName.equals(“”)‖desName.equals(“”))retrurn; pCopyFile=new PrepareCopuFile(this.sourceName,desName); pCopyFile.start(); 应用程序首先从文本框中得到用户选择或输入的源文件或目标文件,如果源文件和目标文件都有不为空,就实例化拷贝线程PrepareCopyFile(该线程目前还不存在),当然首先还必须在类中进行对象定义,方法如下: PrepareCopyFile pCopyFile=null;
190
3. 文件拷贝 退出按钮事件的具体代码如下所示: MessageDialog mdlg=new Message Dialog
3. 文件拷贝 退出按钮事件的具体代码如下所示: MessageDialog mdlg=new Message Dialog (this, ″警告″,″确定要退出吗?″,6); mdlg.setSize(150.80); mdlg.show(); if(mdlg.getResult()==MessageDialog.NO) retrun; System.exit(0); MainFrame类全部源程序清单如下: //源程序清单6-5 package CopyFile; import java.awt.*; import java.awt.event.*; import borland.jbcl.layout.*;
191
3. 文件拷贝 import borland.jbcl.control.*; import.java.io.*;
3. 文件拷贝 import borland.jbcl.control.*; import.java.io.*; import.java.util.*; public class MainFrame extends Frame { TextField textFedle1=new textField(); Bubtton button1=new Button(); Label labell=new Label(); Label labe12=new Label(); TextField textField2=new TextField(); Button button2=new Button(); Button button3=new Button(); Filer filer1=new Filer(″选择源文件″,Filer.LOAD); Filer filer2=new Filer(this,″选择目的文件″, Filer.SAVE);
192
3. 文件拷贝 Button button4=new Button(); PrepareCopyFile pCopyFile=null;
3. 文件拷贝 Button button4=new Button(); PrepareCopyFile pCopyFile=null; Labe label3=new Label(); Panel panel=new Pane(); Panel panel1=new Panel(); PaneLayout paneLayout1=new PaneLayout(); PaneLayout paneLayout2=new PaneLayout(); GroupBox groupBox1=new GroupBox(); List list1=new List(); PaneLayout paneLayout3=new PaneLayout(); Public MainFrame() { try{ jbInit();
193
3. 文件拷贝 catch (Exception e) { e.printStackTrace();
3. 文件拷贝 } catch (Exception e) { e.printStackTrace(); private void jbInit() thows Excption { this.setSize(new Dimension( )); this.setBackgrond(new Color(192,192,192)); button1.setLabl(″浏览...″) btton.addActionListener(new MainFrame_button1_actionAdapter(this)); Btton.addActionListener(new MainFrame_button1_actionAdapter(this)); labell.setAlignment(2);
194
3. 文件拷贝 labell.setText(″源文件″); labell.setAlignment(2);
3. 文件拷贝 labell.setText(″源文件″); labell.setAlignment(2); label2.setText(“目的文件″); button2.setLabel(″复制″); button2.addActionListener(new MainFrame_button2_actionAdapter(this)); button3.setLabel(″退出″); button3.addActionListener(new MainFrame_button3_actionAdapter(this)); button4.setLabel(″浏览...″); button4.addActionListener(new MainFrame_button4_actionAdqapter(this)); label3.setText(“请输入选择源文件(夹)和目标文件(夹):”); groupBox1.setLayout(paneLayout3);
195
3. 文件拷贝 groupBox1.setLabele(″下载队列″); panel1.setLayout(paneLayout2);
3. 文件拷贝 groupBox1.setLabele(″下载队列″); panel1.setLayout(paneLayout2); this.setLayout(paneLayout1); this.add(pane11,new PaneConstraint (″panell″, ″panell″,PaneConstraints.ROOT,0.5f)); panel.add(groupBox1. , new PaneConstraints (“groutpBox1”,“groupBox1”,PaneConstraints.ROOT,1.0f)); GroupBo1.add(list1, new PaneConstraints (“list”,“listl”,PaneConstraint.ROOT,1.0f)); this.add(labe13, new PaneConstraint (“label3”, “panell”,PaneConstraints.LEET, f)); this.add(labell. ,new PaneConstraint (“labell”,“label3”,PaneConstraints.BOTTOM, f))
196
3. 文件拷贝 this.add(textFieldl,new PaneConstraint
3. 文件拷贝 this.add(textFieldl,new PaneConstraint (“label2”,“labell”,PaneConstraints.BOTTOM, f)) this.add(textField,new PaneConstrains (“textField1”,“labell”,PaneConstraints.RIGHT, f)) this.add(buttonl,new PaneConstraints (“buttonl”,“textFieldl”,PaneConstraints.RIGHT, f)); this.add(button2,new PaneConstraints (“button2”,“label2”,PaneConstraints,BOTTOM, f)); this.add(textField2,new PaneConstraints (“textField2”,“Label2”,PaneConstraints.RIGHT, f));
197
3. 文件拷贝 this.add(button4,new PaneConstraints
3. 文件拷贝 this.add(button4,new PaneConstraints (“button4”,“textFileld2”,PaneConstraints.RIGHT, f)); this.add(button3,new PaneConstraints (“button3”,“button2”,PaneConstraints.RIGHT, f)); } public static void main(String[] args) { MainFrame frame=new MainFrame(); frame.setLocation( ); frame.setSize(450,150)l frame.show(); void buttonl_actionPerformed(ActionEvent e) {
198
3. 文件拷贝 filerl.show(); String dir=feler1.getDirectory();
3. 文件拷贝 filerl.show(); String dir=feler1.getDirectory(); String file=feler1.getFile(); if(dir.equals(″null″)&&file.equals(″null″)return; textField1.setText(dir+file); } void button2_actionPerformed(ActionEvent e) { String sourceName=textFileld.getText(); String desName=textField2.getText(); if(sourceName.equals(′′′′)‖desName.equals(′′′′)return; pCopyFile=new PrepareCopyFile(this,sourceName,desName);
199
3. 文件拷贝 pCopyFile.stary(); } void addCopyingFile(String sname) {
3. 文件拷贝 pCopyFile.stary(); } void addCopyingFile(String sname) { File file=new File(same); String sfilename=file.getName(); list1.addItem(sfilename); void removeCopyingFile(String sname) { File file=new File(sname); void button3_actionPerformed(ActionEvent e) { MessageDialog mdlg=new MessageDialog(this,“警告”,确定要退出吗?”,6);
200
3. 文件拷贝 mdlg.setSize(150,80); mdlg.show();
3. 文件拷贝 mdlg.setSize(150,80); mdlg.show(); if(mdlg.getResult()= =MessageDialog.No) return; System.exit(0); } void button4_actionPerformed(ActionEvent e) { filer2.show(); String dir=filer2.getDirectory(); String file=filer2.getFile(); if(dir.equals(″null″)&&file.equals(″null″))return; textField2.setText(dir+file);
201
小结 本章介绍了java的主要可重用类包的结构。具体讲述了java.lang、java.util和jave.io三种java基本的可重用包中常用的类。 java.lang提供了String类和StringBuffer类。String类实现一种不能改变的静态字符串,StringBuffer类实现一种动态可变的字符串。 数组是相同类型的数据元素按顺序组成的一种结构数据类型,元素在数组中的相对位置由下标来指明。数组中的每个元素通过数组名加下标进行引用。 java.util包提供了许多实用的类,如:日期、向量、哈希表、锁和堆栈等。
202
小结 本章还重点介绍了输入输出流操作的基本知识。描述了java输入输出包中字节输入输出流接口、类的层次继承关系。具体介绍了基本输入输出流中的InputStream类、OutputStream类以及System.in和System.out对象的应用,介绍了主要的文件操作方法。例如File类、FileInputStream类、FileOutputStream类、DataInputStream类、DataOutputStream类、ObjectInputStream类和ObjectOutputStream类,并用了建立文件和输入输出流并进行输入输出的实例,说明这些类的应用。
203
习题 1.利用StringBuffer类编写从键盘读入字符串、整数、实型数并在屏幕显示。 2.利用数组,初始化成10个整数,将其排序。
3.利用Vector类,实现一个先进先出队列。 4.利用Vector类,实现一个后进先出栈。 5.利用递归计算N! 的值。 6.利用单向链实现一个先进先出队列。 7.利用单向链实现一个后进先出栈。 8.什么叫流?简述流的分类。 9.节点流与过滤流各有什么特点? 10.编程完成下列功能:建立两个文件myfiel.txt和myfile2.txt,对文件myfile1.txt输入内容“I am a student.”,并将其内容拷贝给myfile2.txt。然后再将myfile2.txt中的内容输出到屏幕。
204
习题 11.编程:键盘输入文件所在目录,再输入文件的文件名。判断该文件是否存在,若存在显示文件相关属性(如文件名、文件的绝对路径文件是否可读、可写等);若文件不存在,显示文件不存在的信息。 12.读下面的程序Main1.java,然后写出程序功能及运行结果。 import java.io.BufferedInputSrteam; import java.io.FileInputStream; import java.io.IOException; Class Main1 { public static void main(String[ ]args) { if(args.length!=1) { System.err,println(Usage:java Main1file); System.exit(-1);
205
习题 } Try { FileInputStream in=new FileInputStream(args[0]);
BufferedInputStreambufin=new BufferedInputStream(in,1024); int count,half=bufin.available( )/2; bufin.skip(half); byte[ ]buf=new byte[1024]; While ((count=bufin.read(buf,0,buf.length))0) for(int i=;icount;i++) System.out.print((char)buf[i]); System.out.flush( ); bufin.close( );
206
习题 (IOException e) { e.printStackTrace( ); }
运行程序时,输入java Main1 c:\apple\myfile.java,其中文件c:\apple\myfile.java的内容为“I am apple!”。 13.试述下面程序完成的功能。 inport java.io.*; class Main2 { public static void main(String[ ]args) { if (args.length!=1) { System.err.println(Usage:java Main2output file); Sytem.exit(-1); }
207
习题 FileOutputStream file_out; DataOutputStream data_out; Try {
file_out=new FileOutputStream(args[0]) data_out=new DataOutputStream(file_out); char a=a byte b=2; String c=abc; short d=4; byte[ ]b2={65,66,67}; data_out.write(b); data_out.write(b2,0,b2,length); data_out.writeBoolean(true); data_out.writeChar(a);
208
习题 data_out.writeBytes(c); data_out.writeChar(c);
data_out.write( f); data_out.write(678); data_out.write(6781); data_out.writeShort(d); data_out.flush( ); System.out.println(Sizeoffilewritten:+data_out.size( )); data_out.close( ); { catch(IOException e) { System.out.println(e); } }
209
部分习题参考答案 public class XiTi6_2 {public static void main(String[] args)
2. 建一数组, 初始化成10个整数, 再将其排序。(冒泡排序) public class XiTi6_2 {public static void main(String[] args) {int i,j,a[ ]={1,6,9,4,3,5,2,7,8,10}; boolean f=false; for(i=0;i<9;i++) {for(j=0;j<9-i;j++) if(a[j]>a[j+1]) {int b=a[j];a[j]=a[j+1];a[j+1]=b; f=true; } if(!f) break; f=false; } for(i=0;i<10;i++) System.out.print(a[i]); 考虑:数组的10个整数随机产生或由键盘输入,程序如何写?
210
部分习题参考答案 3.利用Vector类,实现一个先进先出队列。 import java.util.*;
public class Queue extends Vector {public void inqueue(Object obj) //入队 { addElement(obj); } public Object outqueue() //出队 { Object b=firstElement(); removeElementAt(0); return b; }
211
部分习题参考答案 public static void main(String args[])
{Queue q1= new Queue(); q1.inqueue("111"); q1.inqueue("222"); Object bb=q1.outqueue(); System.out.println(bb); q1.inqueue("333"); bb=q1.outqueue(); } 运行结果: 111 222 333 运行结果
212
部分习题参考答案 import java. io.*; public class XiTi6_10
10. 编程完成下列功能:建立两个文件myfiel.txt和myfile2.txt,对文件myfile1.txt输入内容“I am a student.”,并将其内容拷贝给myfile2.txt。然后再将myfile2.txt中的内容输出到屏幕。 import java. io.*; public class XiTi6_10 public static void main(String[]args)throws Exception {File f = new File("d:\\XiTi6\\myfile1.txt"); FileWriter f1= new FileWriter(f); f1.write("I am a student."); f1.close(); char a[]=new char[(int)f.length()]; FileReader f2 = new FileReader(f); f2.read(a); f2.close();
213
部分习题参考答案 f= new File("d:\\XiTi6\\myfile2.txt");
//上句可改为 f=new File(f.getParent()+"\\myfile2.txt"); f1 = new FileWriter(f); f1.write(a); f1.close(); f2 = new FileReader(f); char b[]=new char[(int)f.length()]; f2.read(b); System.out.println(b); f2.close(); }
Similar presentations