Java程序设计教学做一体化教程第7章输入、输出流.ppt
第 1 页1 页,注意:开始用功了!,第 1 页2 页,配合例子源代码一起使用,Power point 制作:耿祥义 张跃平,输入、输出流,Java程序设计教学做一体化教程 第7章,第 1 页3 页,主要内容,第 1 页4 页,7.1 File类 7.1.1核心知识 _1,1构造方法 File类在java.io包中,程序使用File的对象来获取文件本身的一些信息,例如文件所在的目录、文件的长度、文件读写权限等。File类的构造方法有三个:File(String filename);File(String directoryPath,String filename);File(File dir,String filename);其中,filename是文件名字,directoryPath是文件的路径,dir为一个目录。使用File(String filename)创建文件时,该文件被认为与当前应用程序在同一目录中。,第 1 页5 页,7.1.1 核心知识 _2,2File类的常用方法 public String getName()获取文件的名字。public boolean canRead()判断文件是否是可读的。public boolean canWrite()判断文件是否可被写入。public boolean exits()判断文件是否存在。public long length()获取文件的长度(单位是字节)。public String getAbsolutePath()获取文件的绝对路径。public String getParent()获取文件的父目录。public boolean isFile()判断文件是否是一个普通文件,而不是目录。public boolean isDirectroy()判断文件是否是一个目录。public boolean isHidden()判断文件是否是隐藏文件。public long lastModified()获取文件最后修改的时间(时间是从1970年午夜至文件最后修改时刻的毫秒数)。更多方法见page 140.,第 1 页6 页,7.1.2 能力目标,掌握File类的常用方法。,第 1 页7 页,7.1.3 任务驱动,将下列Application7_1.java中的【代码】替换为程序代码。程序运行效果如图7.1。,第 1 页8 页,任务小结,(1)使用File类创建一个文件对象后,例如File file=new File(c:myletter,letter.txt);如果c:myletter目录中没有名字为letter.txt文件,文件对象file调用方法:public boolean createNewFile();可以在c:myletter目录中建立一个名字为letter.txt的文件。(2)文件对象调用方法public boolean delete()可以删除当前文件,例如:file.delete();,第 1 页9 页,7.1.4 实践环节,上机调试下列程序,并注意Runtime对象是怎样运行windows平台上的记事本程序和浏览器程序的。Appilcation7_2.java,第 1 页10 页,7.2 文件字节输入流 7.2.1 核心知识_1,FileInputStream类的对象称为文件字节输入流,文件字节输入流以字节为单位读取文件中的内容。1创建指向文件的字节输入流 使用FileInputStream类的下列构造方法创建指向文件的输入流。FileInputStream(String name);FileInputStream(File file);程序必须在try-catch语句中的try块部分创建输入流、在catch(捕获)块部分检测并处理这个异常。例如,为了读取一个名为hello.txt的文件,建立一个文件字节输入流in:,或File f=new File(hello.txt);try FileInputStream in=new FileInputStream(f);catch(IOException e)System.out.println(File read error:+e);,try FileInputStream in=new FileInputStream(hello.txt);catch(IOException e)System.out.println(File read error:+e);,第 1 页11 页,7.2.1 核心知识 _2,2以字节为单位读文件 文件字节流可以调用从父类(InputStream)继承的read方法顺序地、以字节为单位读取文件,只要不关闭流,每次调用read方法就顺序地读取文件中的其余内容,直到文件的末尾或文件字节输入流被关闭。int read()输入流调用该方法从源中读取单个字节的数据,该方法返回字节值(0255之间的一个整数),如果未读出字节就返回-1。int read(byte b)输入流调用该方法从源中试图读取b.length个字节到字节数组b中,返回实际读取的字节数目。如果到达文件的末尾,则返回-1。int read(byte b,int off,int len)输入流调用该方法从源中试图读取len个字节到字节数组b中,并返回实际读取的字节数目。如果到达文件的末尾,则返回-1,参数off指定从字节数组的某个位置开始存放读取的数据。例如,如果文件字节输入流in指向的文件的内容是apple is very good,那么in首次调用read()方法:int m=in.read();将读取文件中的第一个字节,即读取到字母a,并返回字母a的字节值(97),即m的值是97。,第 1 页12 页,7.2.1 核心知识 _3,3关闭流 输入流都提供了关闭方法close(),尽管程序结束时会自动关闭所有打开的流,但是当程序使用完流后,显式地关闭任何打开的流仍是一个良好的习惯。如果没有关闭那些被打开的流,那么就可能不允许另一个程序操作这些流所用的资源。,第 1 页13 页,7.2.2 能力目标,使用文件字节输入流读取文件。,第 1 页14 页,7.2.3 任务驱动,将下列Application7_3.java中的【代码】替换为程序代码。程序运行效果如图7.2。,第 1 页15 页,任务 小结,程序在运行期间,可能需要从外部的存储媒介或其他程序中读入所需要的数据,这就需要使用输入流。输入流的指向称为它的源,程序通过输入流读取源中的数据。比如,程序需要读取文件,那么就可以使用FileInputStream建立一个和文件相连接的文件字节输入流,如图7.3所示。,使用输入流通常包括4个基本步骤:(1)设定输入流的源,比如磁盘上的文件。(2)创建指向源的输入流(3)让输入流读取源中的数据(4)关闭输入流。,第 1 页16 页,7.3 文件字节输出流 7.3.1 核心知识_1,FileOutputStream类的对象称为文件字节输出流,文件字节输出流以字节为单位向文件写入数据,即以字节为单位写文件。1创建指向文件的文件字节输出流 可以使用FileOutputStream类的下列具有刷新功能的构造方法创建指向文件的输出流。FileOutputStream(String name);FileOutputStream(File file);需要特别注意的是,如果输出流指向的文件不存在,Java就会创建该文件,如果执向的文件是已存在的文件,输出流将刷新该文件。可以使用FileOutputStream类的下列能选择是否具有刷新功能的构造方法创建指向文件的输出流。FileOutputStream(String name,boolean append);FileOutputStream(File file,boolean append);,第 1 页17 页,7.3.1 核心知识 _2,2以字节为单位写文件 文件字节流可以调用从父类继承的write方法顺序地写文件。FileOutStream流顺序地向文件写入内容,即只要不关闭流,每次调用write方法就顺序地向文件写入内容,直到流被关闭。void write(int n)输出流调用该方法向文件写入单个字节。void write(byte b)输出流调用该方法向文件写入一个字节数组。void write(byte b,int off,int len)给定字节数组中起始于偏移量off处取len个字节写到文件。void close()关闭输出流。,第 1 页18 页,7.3.2 能力目标,能使用文件字节输出流写文件。,第 1 页19 页,7.3.3 任务驱动,将下列Application7_4.java中的【代码】替换为程序代码。程序运行效果如图7.4。,第 1 页20 页,任务 小结,程序在处理数据后,要将处理的结果写入到永久的存储媒介中或传送给其他的应用程序,就需要使用输出流。输出流的指向称为它的目的地,程序通过输出流把数据传送到目的地。比如,程序需要将数据写入到文件,那么就可以使用FileOutputStream建立一个和文件相连接的文件字节输出流,如图7.5所示。,使用输出流通常包括4个基本步骤:(1)给出输出流的目的地,比磁盘上的文件(2)创建指向目的地的输出流(3)让输出流把数据写入到目的地(4)关闭输出流。,第 1 页21 页,7.3.4 实践环节,上机调试程序,观察程序的运行结果。Application7_5.java,第 1 页22 页,7.4 文件字符输入、输出流 7.4.1 核心知识,文件字节输入、输出流以字节为单位处理数据。因此,字节流不能很好地操作Unicode字符,比如,一个汉字在文件中占用2个字节,如果使用字节流,读取不当会出现“乱码”现象。与FileInputStream、FileOutputStream字节流相对应的是FileReader、FileWriter字符流,FileReader和FileWriter分别是Reader和Writer的子类,其构造方法分别是:FileReader(String filename);FileReader(File filename);FileWriter(String filename);FileWriter(File filename);FileWriter(String filename,boolean append);FileWriter(File filename,boolean append);字符输入流和输出流的read和write方法使用字符数组读写数据,即以字符为基本单位处理数据。,第 1 页23 页,7.4.2 能力目标,使用文件字符输入、输出流读写文件。,第 1 页24 页,7.4.3 任务驱动,将Application7_6.java中的【代码】替换为程序代码。程序运行效果如图7.6。,第 1 页25 页,任务 小结,Writer字符流的write方法将数据首先写入到缓冲区,每当缓冲区溢出时,缓冲区的内容被自动写入到目的地,如果关闭流,缓冲区的内容会立刻被写入到目的地。流调用flush()方法可以立刻冲洗当前缓冲区,即将当前缓冲区的内容写入到目的地。因此,当使用字符输出流完成数据写入之后,一定要关闭输出流。,第 1 页26 页,7.5 缓冲流 7.5.1 核心知识_1,如果按行读取文件的内容,那么在不清楚一行有多少个字符的情况下,FileReader流的read方法很难完成这样的任务。1BufferReader流 BufferedReader流称为缓冲输入流,相对于FileReader流,缓冲输入流增强了读文件的能力。通过向BufferedReader传递一个Reader子类的对象(如FileReader的实例),来创建一个BufferedReader对象,如:FileReader inOne=new FileReader(Student.txt)BufferedReader inTwo=BufferedReader(inOne);上述代码可以通俗地理解成inTwo流和inOne流连接在了一起,那么inTwo流也就可以读取inOne流指向的文件了,比如inTwo流就具有readLine()方法(按行读取文件),例如:String strLine=inTwo.readLine();,第 1 页27 页,7.5.1 核心知识 _2,2BufferWriter流 BufferedWriter流称为缓冲输入流,相对于FileWriter流,缓冲输出流增强了写文件的能力。可以将BufferedWriter流和FileWriter流连接在一起,然后使用BufferedWriter流将数据写到目的地,例如:FileWriter tofile=new FileWriter(hello.txt);BufferedWriter out=BufferedWriter(tofile);然后out使用BufferedReader类的方法 write(String s,int off,int len)把字符串s写到hello.txt中,参数off是s开始处的偏移量,len是写入的字符数量。另外,BufferedWriter流有一个独特的向文件写入一个回行符的方法:newLine();,第 1 页28 页,7.5.2 能力目标,使用缓冲流读写文件。,第 1 页29 页,7.5.3 任务驱动,将下列Application7_7.java中的【代码】替换为程序代码。english.txt程序运行效果如图7.7。,第 1 页30 页,任务 小结,可以把BufferedReader和BufferedWriter称为上层流,把它们指向的字符流称为底层流。底层字符输入流首先将数据读入缓存,BufferedReader流再从缓存读取数据;BufferedWriter流将数据写入缓存,底层字符输出流会不断地将缓存中的数据写入到目的地。当BufferedWriter流调用flush()刷新缓存或调用close()方法关闭时,即使缓存没有溢满,底层流也会立刻将缓存的内容写入目的地。关闭输出流时要首先关闭缓冲输出流,然后关闭缓冲输出流指向的流。在编写代码时只需关闭上层流,那么上层流的底层流将自动关闭。,第 1 页31 页,7.5.4 实践环节,test.txt是一套标准化考试的试题文件。下面的代码每次读取试题文件中的一道题目,并等待用户回答,用户做完全部题目后,程序给出用户的得分。调试下列代码,并注意程序是怎样使用输入流读取试题文件的,程序效果如图7.8。Application7_8.java StandardExam.java,第 1 页32 页,7.6 随机流 7.6.1 核心知识_1,1RandomAccessFile类 RandomAccessFile类创建的流称作随机流,RandomAccessFile流的指向既可以作为源、也可以作为目的地。简单地说,使用RandomAccessFile流不仅能读文件,也可以写文件。以下是RandomAccessFile类的两个构造方法。RandomAccessFile(String name,String mode)参数name 用来确定一个文件名,给出创建的流的源,也是流目的地。参数mode取r(只读)或rw(可读写),决定创建的流对文件的访问权利。RandomAccessFile(File file,String mode)参数file 是一个File对象,给出创建的流的源,也是流目的地。参数mode取r(只读)或rw(可读写),决定创建的流对文件的访问权利。,第 1 页33 页,7.6.1 核心知识 _2,2常用方法 RandomAccessFile类中有一个方法seek(long a),用来定位RandomAccessFile流的读写位置,其中参数a确定读写位置距离文件开头的字节个数。调用getFilePointer()方法获取流的当前读写位置。RondomAccessFile流的readLine()方法按行读取文件,但在读取含有非ASCII字符的文件时会出现“乱码”现象,因此,需要把readLine()读取的字符串用“iso-8859-1”编码重新编码存放到byte数组中,然后再用当前机器的默认编码将该数组转化为字符串,操作如下:(1)读取 String str=in.readLine();(2)用“iso-8859-1”重新编码 byte b=str.getBytes(iso-8859-1);(3)使用当前机器的默认编码将字节数组转化为字符串 String content=new String(b);,第 1 页34 页,7.6.2 能力目标,能使用RondomAccessFile流读取文件。,第 1 页35 页,7.6.3 任务驱动,将下列Application7_9.java中的【代码】替换为程序代码。程序运行效果如图7.9。,第 1 页36 页,任务 小结,与前面的输入、输出流不同的是,RandomAccessFile类既不是InputStream类的子类,也不是OutputStram类的子类。当准备对一个文件进行读写操作时,可以创建一个指向该文件的随机流,可以从这个随机流读取文件的数据,也可以通过这个随机流写数据到文件。另外,随机流指向文件时,不刷新文件。,第 1 页37 页,表7.1 RandomAccessFile类的常用方法,第 1 页38 页,7.6.4 实践环节,表7.1是RandomAccessFile流的常用方法。下列代码将几个整数写入文件,然后按写入的顺序倒序读出所写入的整数。上机调试下列代码,熟悉RandomAccessFile流的常用方法。Application7_10.java,第 1 页39 页,7.7 数据流 7.7.1 核心知识_1,DataInputStream和DataOutputStream类创建的对象称为数据输入流和数据输出流。它们允许程序按着机器无关的风格读取Java原始数据。以下是DataInputStream和DataOutputStream的构造方法。DataInputStream(InputStream in)创建的数据输入流指向一个由参数in指定的底层输入流。DataOutputStream(OutnputStream out)创建的数据输出流指向一个由参数out指定的底层输出流。表7.2是DataInputStream和DataOutputStream类的常用方法。,第 1 页40 页,表7.2 DataInputStream及DataOutputSteam类的部分方法,第 1 页41 页,7.7.2 能力目标,使用数据流读、写文件。,第 1 页42 页,7.7.3 任务驱动,将下列Application7_11.java中的【代码】替换为程序代码.程序运行效果如图7.10,第 1 页43 页,任务 小结,数据流输入流不能直接指向文件,必须指向一个InputStream子类创建的流,这个流称为数据输入流的底层流,底层流负责指向文件。同样,数据流输出流不能直接指向文件,必须指向一个OutputStream子类创建的流,这个流称为数据输出流的底层流,底层流负责指向文件。,第 1 页44 页,7.7.4 实践环节,请上机调试下列代码,并注意程序的运行效果。Application7_12.java EncryptAndDecrypt.java,第 1 页45 页,7.8 解析文件 7.8.1 核心知识,1使用默认分隔标记解析文件创建Scanner对象,并指向要解析的文件,例如:File file=new File(hello.java);Scanner sc=new Scanner(file);那么sc将空格作为分隔标记、调用next()方法依次返回file中的单词,如果file最后一个单词已被next()方法返回,sc调用hasNext()将返回false,否则返回true。2使用正则表达式作为分隔标记解析文件 创建Scanner对象,指向要解析的文件,并使用useDelimiter方法指定正则表达式作为分隔标记,例如:File file=new File(hello.java);Scanner sc=new Scanner(file);sc.useDelimiter(正则表达式);那么sc将正则表达式作为分隔标记,调用next()方法依次返回file中的单词,如果file最后一个单词已被next()方法返回,sc调用hasNext()将返回false,否则返回true。,第 1 页46 页,7.8.2 能力目标,使用Scanner流解析文件中的数据。,第 1 页47 页,7.8.3 任务驱动,word.txt将下列Application7_13.java中的【代码】替换为程序代码。程序运行效果如图7.11。,第 1 页48 页,任务 小结,对于数字型的单词,比如108,167.92等可以用nextInt()或nextDouble()方法来代替next()方法,即Scanner对象sc可以调用nextInt()或nextDouble()方法将数字型单词转化为int或double数据返回.但需要特别注意的是,如果单词不是数字型单词,调用nextInt()或nextDouble()方法将发生InputMismatchException异常,在处理异常时可以调用next()方法返回该非数字化单词。,第 1 页49 页,7.8.4 实践环节,上机调试下列代码,注意Scanner流是怎样解析文件中的数字单词的。Application7_14.java,第 1 页50 页,7.9 小结,1InputStream流称为字节输入流,字节输入流按字节读取数据,只要不关闭流,每次调用读取方法时就顺序地读取“源”中的其余的内容,直到“源”中的末尾或流被关闭。2.Reader流称为字符输入流,字符输入流按字符读取源中的数据,只要不关闭流,每次调用读取方法时就顺序地读取“源”中的其余的内容,直到“源”中的末尾或流被关闭。3.OutputStream流称为字节输出流。字节输出流按字节将数据写入目的地,只要不关闭流,每次调用写入方法就顺序地向目的地写入内容,直到流被关闭。4.Writer流称为字符输出流。字符输出流按字符将数据写入目的地,只要不关闭流,每次调用写入方法就顺序地向目的地写入内容,直到流被关闭。,“本节结束咯偶都会了太葱明了”,第 1 页51 页,