java中的输入、输出流.ppt_第1页
java中的输入、输出流.ppt_第2页
java中的输入、输出流.ppt_第3页
java中的输入、输出流.ppt_第4页
java中的输入、输出流.ppt_第5页
已阅读5页,还剩26页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

* 1 第九章 输入、输出流 本章导读 n 文件 n 文件字节流和文件字符流 n 缓冲流 n 数组流和字符串流 n 数据流 n 对象流 n 序列化和对象克隆 n 随机读写流 n 使用Scanner类解析文件 n 文件锁 * 2 输入流、输出流概述 I/O流提供一条通道程序,可以使用这条通道读取“源”中的数据,或把 数据送到“目的地”。 I/O流中的输入流的指向称为源,程序从指向源的输入流中读取源中的数 据(如图9.1所示意); 输出流的指向称为目的地,程序通过向输出流中写入数据把信息传递到目 的地(如图9.2所示意)。 程序的源和目的地也可以是键盘、鼠标、内存或显示器窗口。 * 3 I/O流库提供的4个重要的abstract类 Java的I/O流库提供大量的流类(在包java.io中),其中有4个 重要的abstract类: InputStream 字节输入流 Reader 字符输入流 OutputStream 字节输出流 Writer字符输出流 InputStream和Reader类为其子类提供了重要的读取数据 的read()方法. OutputStream和Writer类为其子类提供了重要的写入数据 的write()方法。 * 4 9.1 文件 多流的读写与文件有关。 Java使用File类创建的对象来获取文件本身的一些 信息,如文件所在的目录、文件的长度、文件读写权限 等,文件对象并不涉及对文件的读写操作。 创建一个File对象的构造方法有3个: File(String filename); File(String directoryPath,String filename); File(File f, String filename); 其中filename是文件名字,directoryPath是文件的 路径,f是一个目录。 使用File(String filename)创建文件时,该文件被认为 是与当前应用程序在同一目录中。 * 5 1文件的属性 使用File类的下列方法可以获取文件本身的一些信息: 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 年午夜至文件最后修改时刻的毫秒数。 * 6 2目录 1)创建目录 public boolean mkdir() 创建一个目录,创建成功返回true,否则返回false。 2)列出目录中的文件(如果File对象是一个目录) public String list() 用字符串形式返回目录下的全部文件。 public File listFiles() 用File对象形式返回目录下的全部文件。 File类的下述两个方法可以列出指定类型的文件: public String list(FilenameFilter obj) 该方法用字符串形式返回目录 下的指定类型的所有文件。 public File listFiles(FilenameFilter obj) 该方法用File对象返回目 录下的指定类型所有文件。 FilenameFilter是一个接口,该接口有一个方法: public boolean accept(File dir,String name); 使用list()方法时,需向该方法传递一个实现FilenameFilter接口的对象。list()方 法执行时,参数不断回调接口方法accept(File dir,String name),参数name被实例 化目录中的一个文件名,参数dir为调用list的当前对象,当接口方法返回true时, list()方法就将目录dir中的文件存放到返回的数组中。 * 7 3文件的创建与删除 对于 File f=new File(“C:myletter“,“letter.txt“); 如果C:myletter目录中没有名字为letter.txt的文件,文件对象f 调用方法 public boolean createNewFile() 可以在C:myletter目录中建立一个名字为letter.txt的文件 。 文件对象调用方法 public boolean delete() 可以删除当前文件,如 f.delete(); 例9-1列出了D:ch9目录下java源文件的名字及其大小,并删 除了D:ch9中的一个java源文件。 * 8 4运行可执行文件 使用java.lang包中的Runtime类,执行一个本地机上的可执行 文件。 首先使用Runtime类声明一个对象,如 Runtime ec; 然后使用该类的静态getRuntime()方法创建这个对象: ec=Runtime.getRuntime(); ec可以调用exec(String command)方法打开本地的可执行文 件或执行一个操作。 例9-2中,Runtime对象打开Windows平台上的绘图程序和记事 本程序。 * 9 9.2 文件字节流 1FileInputStream类 FileInputStream类是InputStream的子类,称为文件字节输入流,按字节读取 文件中的数据。该类的所有方法都是从InputStream类继承来的。构造方法: FileInputStream(String name) FileInputStream(File file) 构造方法参数指定的文件称为输入流的源,输入流通过使用read()方法从输入流 读出源中的数据。 建立一个文件输入流对象,代码如下: try FileInputStream ins = new FileInputStream(“myfile.dat“); catch (IOException e ) System.out.println(e ); read()方法的形式 : int read();从输入流中顺序读取单个字节的数据 int read(byte b )和int read(byte b ,int off,int len) 把多个字节读到一 个字节数组中,返回实际读取的字节个数。参数off指定read()方法把数据存放在字节数 组b中的位置,参数len指定该方法将读取的最大字节数。 FileInputStream流顺序地读取文件,只要不关闭流,每次调用read()方法就顺序 地读取文件中其余的内容,直到文件的末尾或流被关闭。 * 10 2FileOutputStream类 FileOutputStream提供了基本的文件写入能力,是OutputStream的子类,称 为文件字节输出流。文件字节输出流按字节将数据写入到文件中.构造方法: FileOutputStream(String name) FileOutputStream(File file) FileOutputStream(String name, boolean append) FileOutputStream(File file, boolean append) 构造方法参数指定的文件称为输出流的目的地。输出流使用write()方法把 数据写入输出流到达目的地。 public void write(byte b) 写b.length个字节到输出流。 public void.write(byte b,int off,int len) 从给定字节数组中起始于偏移量 off处写len个字节到输出流,参数b是存放了数据的字节数组。 只要不关闭流,每次调用writer()方法就顺序地向文件写入内容,直到流 被关闭 例9-3中,首先将“欢迎welcom”写入到文件“hello.txt”中,然后再读取 该文件中的内容。 * 11 9.3 文件字符流 1FileReader类 FileReader类是Reader的子类,称为文件字符输入流。文件字符输入流按字符 读取文件中的数据。构造方法: FileReader(String name) FileReader (File file) 构造方法参数指定的文件称为输入流的源,输入流通过使用read()方法从输 入流读出源中的数据。 int read() 输入流调用该方法从源中读取一个字符。该方法返回一个整数(0 65535之间的一个整数,Unicode字符值),如果未读出字符就返回1。 int read(char b ) 输入流调用该方法从源中读取b.length个字符到字符数组b 中,返回实际读取的字符数目。如果到达文件的末尾,则返回-1。 int read(char b ,int off,int len) 输入流调用该方法从源中读取len个字符 并存放到字符数组b中,返回实际读取的字符数目。如果到达文件的末尾,则返回-1。 其中,参数off指定该方法从字符数组b中的什么地方存放数据。 * 12 2FileWriter类 FileWriter提供了基本的文件写入能力。FileWriter类是Writer的子类,称为 文件字符输出流。文件字符输出流按字符将数据写入到文件中.构造方法: FileWriter(String name); FileWriter (File file); FileWriter (String name, boolean append); FileWriter (File file, boolean append); 构造方法参数指定的文件称为输出流的目的地。输出流使用write()方法把数 据写入输出流到达目的地。 public void write(char b) 写b.length个字符到输出流 public void.write(char b,int off,int len) 从给定字符数组中起始于偏移量 off处写len个字符到输出流,参数b是存放了数据的字符数组 void write(String str) 把字符串中的全部字符写入到输出流 void write(String str,int off,int len) 从字符串str中起始于偏移量off处写len 个字符到输出流 只要不关闭流,每次调用writer()方法就顺序地向文件写入内容,直到流被关闭 例9-4首先用字符输出流向一个已经存在的文件尾加若干个字符,然后再用字符输入 流读出文件中的内容。 * 13 9.4 缓冲流 (教材印刷错误9.5) 1BufferedReader类 BufferedReader类创建的对象称为缓冲输入流,该输入流的指向必须是一个Reader流,称为 BufferedReader流的底层流,底层流负责将数据读入缓冲区。 BufferedReader流的源就是这个缓冲区,缓冲输入流再从缓冲区中读取数据。 可以将BufferedReader与FileReader连接,然后BufferedReader就可以按行读FileReader指 向的文件。BufferedReader的构造方法如下: BufferedReader(Reader in) BufferedReader流能够读取文本行,方法是 readLine() 可以向BufferedReader传递一个Reader对象(如FileReader的实例)来创建一个 BufferedReader对象: FileReader inOne=new FileReader(“Student.txt“) BufferedReader inTwo=new BufferedReader(inOne); 然后inTwo调用readLine()顺序读取文件“Student.txt”的一行。 * 14 2BufferedWriter类 可以将BufferedWriter流和FileWriter流连接在一起,然后 使用BufferedWriter流将数据写到目的地。 FileWriter流称为BufferedWriter的底层流, BufferedWriter流将数据写入缓冲区,底层流负责将数据写到最 终的目的地。例如, FileWriter tofile=new FileWriter(“hello.txt“); BufferedWriter out=new BufferedWriter(tofile); BufferedReader流调用方法: write(String str) write(String s,int off,int len) 把字符串s或s的一部分写入到目的地。 BufferedWriter调用newLine()方法,可以向文件写入一个回行 ,调用flush()可以刷新缓冲区。 例9-5将文件“Student.txt”中的内容按行读出,并写入到 另一个文件中,且给每一行加上行号 * 15 3标准化考试 标准化试题文件的格式要求如下: 每道题目之间用一个或多个星号(*)字符分隔(最后一个题目 的最后一行也是*)。 每道题目提供A、B、C、D四个选择(单项选 择)。 test.txt是一套标准化考试的试题文件。 例9-6使用输入流读取试题文件,每次显示试题文件中的一道 题目。当读取到字符*时,暂停读取,等待用户从键盘输入答案。用 户做完全部题目后,程序给出用户的得分。程序运行效果如图9.3 。 * 16 9.5 数组流 (教材印刷错误9.6) 流的源和目标除了可以是文件外,还可以是计算机内存。 ByteArrayInputStream和字节输出流ByteArrayOutputStream分别使用字节数组作 为流的源和目标。 数组字节输入流 ByteArrayInputStream构造方法如下 ByteArrayInputStream(byte buf) ByteArrayInputStream(byte buf,int offset,int length) 数组字节输 入流调用 public int read() 顺序地从源中读出一个字节,该方法返回读出的字节值 public int read(byte b,int off,int len)顺序地从源中读出参数len指定的字节数,并将读出的字节 存放到参数b指定的数组中,参数off指定数组b存放读出字节的起始位置,该方法返回实际读出的 字节个数。如果未读出字节read方法返回-1。 数组字节输出流 ByteArrayOutputStream的构造方法如下: ByteArrayOutputStream() ByteArrayOutputStream(int size) 字节数组字节输 出流调用 public void write(int b) 顺序地向缓冲区写入一个字节 public void write(byte b,int off,int len)将参数b中指定的len个字节顺序地写入缓冲区,参数 off指定从b中写出的字节的起始位置 public byte toByteArray() 返回输出流写入到缓冲区的全部字节 例9-7向内存(输出流的缓冲区)写入ASCII表,然后再读出这些字节和字节对应的字符 。 * 17 数组字符流 与数组字节流对应的是数组字符流CharArrayReader和 CharArrayWriter类,数组字符流分别使用字符数组作为流的源 和目标。 与数组字节流不同的是,数组字符流的读操作可能发生 IOException异常。 例9-8将Unicode表中的一些字符写入内存,然后再读出。 * 18 9.6 字符串流 (教材印刷错误9.7) StringReader使用字符串作为流的源。构造方法: public StringReader(String s) 构造的输入流指向参数s指定的字符串 字符串输入流调用 public int read() 顺序读出源中的一个字符,并返回字符在Unicode表中的位置 public int read(char buf,int off,int len)顺序地从源中读出参数len指定的字符个 数,并将读出的字符存放到参数b指定的数组中,参数off指定数组b存放读出字符的起 始位置,该方法返回实际读出的字符个数。 StringWriter将内存作为流的目的地,构造方法: StringWriter()和 StringWriter(int size)可以构造字符串输出流对象 字符串输出流调用: public void write(int b) 向缓冲区写入字符 public void write(char b,int off,int len)向缓冲区写入字符 public void write(String str)向缓冲区写入字符 public void write(String str,int off,int len)向缓冲区写入字符 public String toString() 返回输出流写入到缓冲区的全部字符 public void flush() 可以刷新缓冲区 * 19 9.7 数据流 (教材印刷错误9.8) 1DataInputStream类和DataOutputStream类 DataInputStream 类和DataOutputStream类创建的对象称为数据输入流和 数据输出流。它们允许程序按照与机器无关的风格读取Java原始数据。 2DataInputStream类和DataOutputStream的构造方法 DataInputStream(InputStream in) 创建的数据输入流指向一个由参数in 指定的输入流,以便从后者读取数据(按着机器无关的风格读取)。 DataOutputStream(OutnputStream out)创建的数据输出流指向一个由 参数out指定的输出流,然后通过这个数据输出流把Java数据类型的数据写到 输出流out。 表9.1 DataInputStream类和DataOutputSteam的部分方法 例9-9可以完成写几个Java类型的数据到一个文件,并再读出来。 * 20 表9.1 DataInputStream类和DataOutputSteam的部分方法 * 21 9.8 对象流 (教材印刷错误9.9) ObjectInputStream类和ObjectOutputStream类创建的对象被称为对象输入流 和对象输出流。构造方法: ObjectInputStream(InputStream in) ObjectOutputStream(OutputStream out) 对象输出流使用writeObject(Object obj)方法将一个对象obj写入输出流送往目 的地,对象输入流使用readObject()从源中读取一个对象到程序中。 将一个对象写入到文件时,首先用FileOutputStream创建一个文件输出流, 如下所示: FileOutputStream file_out=new FileOutputStream(“tom.txt“); ObjectOutputStream object_out=new ObjectOutputStream(file_out); 准备从文件中读入一个对象到程序中时,首先用FileInputStream创建一个文 件输入流,如下所示: FileInputStream file_in=new FileInputStream(“tom.txt“); ObjectInputStream object_in=new ObjectInputStream(file_in); 注:当我们使用对象流写入或读入对象时,要保证对象是序列化的。 一个类如 果实现了Serializable接口,那么这个类创建的对象就是序列化的对象。 使用对象流把 一个对象写入到文件时不仅保证该对象是序列化的,而且该对象的成员对象也必须是序 列化的。 例9-10中有一个实现Serializable接口的Goods类。 * 22 9.9 序列化与对象克隆 (教材印刷错误9.10) 有时我们想得到对象的一个“复制品”,该复制品的实体是 原对象实体的拷贝。复制品实体的变化不会引起原对象实体发生 变化。对象调用clone()方法就可以获取对象的“复制品”,称为 原对象的克隆对象。 对象进行克隆时需要特别注意的是:如果原对象有引用型成 员变量,那么克隆对象对应的成员变量的引用就与原对象那个成 员变量的引用相同,克隆对象对自己的这个成员变量所引用的实 体的操作,将影响原对象引用型成员变量的实体。这样一来就涉 及到深度克隆的问题,因为原对象的成员变量中可能还会有其他 对象。因此,程序必须重写clone()方法,增加了编程的难度。 使用对象流很容易获取一个序列化对象的克隆。只需将该对 象写入到对象输出流,然后用对象输入流读回的对象就是原对象 的一个克隆。 例9-11将对象写入到内存,然后读回该对象的一个克隆。 * 23 9.10 随机读写流 (教材印刷错误9.11) 当用户需要严格地处理文件时,就可以使用RandomAccessFile类来创建一 个对象(称为随机读写流)。RandomAccessFile类创建的流的指向既可以作为 源,也可以作为目的地。 RandomAccessFile类有两个构造方法: RandomAccessFile(String name,String mode) 参数name用来确定一个文件名 ,给出创建的流的源,也是流目的地。参数mode取r(只读)或rw(可读写),决定 创建的流对文件的访问权力。 RandomAccessFile(File file,String mode) 参数file是一个File对象,给出创建 的流的源,也是流目的地。参数mode取r(只读)或rw(可读写),决定创建的流对 文件的访问权力。 流还可以调用 seek(long a) 用来移动RandomAccessFile流的读写位置,其中参数a确定读 写位置距离文件开头的字节位置。 getFilePointer() 获取当前流在文件中的读写的位置。 表9.2给出了RandomAccessFile的常用方法。 * 24 表9.2 RandomAccessFile的常用方法 * 25 例题9-12,例题9-12 例9-12 把5个int类型整数写入到一个名字为tom.dat文件中,然后按相反 顺序读出这些数据。一个int类型数据占4个字节,首先将读写位置移动到文件 的第16个字节位置,读取tom.dat文件中最后一个整数,然后将读写位置再移 动到文件的第12个字节,读取tom.dat文件中倒数第二个整数,依次类推将 tom.dat文件中的整数按相反顺序读出。 注: 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); 如果机器的默认编码是“GB2312”,那么 String content=new String(b); 等同于: String content=new String(b, “GB2312“); 例9-13中RondomAccessFile流使用readLine()读取一个文件。 * 26 9.11使用Scanner解析文件 (教材印刷错误9.12) 应用程序可能需要解析文件中的特殊数据,此时,应用程序 可以把文件的内容全部读入内存后,再使用第6章的有关知识解 析所需要的内容,其优点是处理速度快,但如果读入的内容较大 将消耗较多的内存,即以空间换取时间。 本节介绍怎样借助Scanner类和正则表达式来解析文件,比如 ,要解析出文件中的特殊单词,数字等信息。使用Scanner类和正 则表达式来解析文件的特点是以时间换取空间,即解析的速度相 对较慢,但节省内存。 * 27 1使用默认分隔标记解析文件 创建Scanner对象,并指向要解析的文件,例如: File file = new File(“hello.java“); Scanner sc = new Scanner(file); 那么sc将空格作为分隔标记 、调用next()方法依次返回file中的单词 ,如果file最 后一个单词 已被next()方法返回,sc调用hasNext()将返回false,否则返回true。 对于数字型的单词 ,比如108,167.92等可以用nextInt()或nextDouble()方法来代 替next()方法,即sc可以调用nextInt()或nextDouble()方法将数字型单词转 化为 int或double数据返回,但需要特别注意的是,如果单词 不是数字型单词 ,调用 nextInt()或nextDouble()方法将发生InputMismatchException异常,在处理异常时 可以调用next()方法返回该非数字化单词 。 假设cost.txt的内容如下: TV cost 876 dollar,Computer cost 2398 dollar.The milk cost 98 dollar. The apple cost 198 dollar. 例9-14中使用Scanner对象解析文件cost.txt中的 全部消费并计算出总消费。程序运行效果如图9.4 * 28 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。 对于数字型的单词 ,比如1979,0.618等可以用nextInt()或nextDouble()方法 来代替next()方法,即sc可以调用nextInt()或nextDouble()方法将数字型单词转 化为int或double数据

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论