1、教学目标教学目标n输入和输出流概述n输入流和输出流n字节流和字符流n输入和输出类的继承层次结构nFile类n基于字节的输入和输出类及应用实例n抽象类InputStream和OutputStreamnFileInputStream和FileOutputStream类n随机访问文件类n过滤字节流 教学目标教学目标(续续)n标准输入输出流n对象流n管道流n内存读写流n序列输入流n基于字符的输入和输出类及应用实例nInputStreamReader和OutputStreamWriter类nBufferedReader和BufferedWriter类n其它字符流 11.1 输入和输出流概述输入和输出流概
2、述11.1.1 11.1.1 输入流和输出流输入流和输出流n 程序往往需要输入/输出处理,比如n从键盘读取数据、向屏幕中输出数据、从文件中读数据n或者向文件中写数据、在一个网络连接上进行读写操作等。n在Java中,把这些不同类型的输入、输出源抽象为流(Stream)11.1.1 11.1.1 输入流和输出流输入流和输出流nJava的流分类:n输入流输入流(Input Stream):能够读取字节序列的对象,n输出流输出流(Output Stream):能够写字节序列的对象。如:一个文件,当向其中写数据时,它就是一个输出流;当从其中读取数据时,它就是一个输入流。如:键盘是一个输入流,屏幕是一个输
3、出流。11.1.2 11.1.2 字节流和字符流字节流和字符流 nJava 2定义了两种类型的流:n字节流字节流:以byte(8 bits)为基本处理单位的流,这些类分别由抽象类InputStream和OutputStream派生的类层次。n字符流字符流:处理使用Unicode(每个字符使用两个字节)的数据,是从抽象类Reader和Writer的派生的类层次,用于读写双字节的Unicode字符.面向字节流的输入输出类层次结构 面向字符流的输入输出类层次结构 11.2 File11.2 File类类n File类主要用于获取磁盘中文件或目录的各种信息。n构造File类对象的构造函数:public
4、 Fle(String pathName)指定与File对象关联的文件或目录的名称。pathName可以是包含路径信息的文件名或目录名。路径可为绝对路径或为相对路径。11.2 File11.2 File类类(续续)例如:File f=new File(“datatemp.dat”);/相对路径 File g=new File(“d:javadatatemp.dat”);/绝对路径nFileFile类的一些常见方法:类的一些常见方法:String getName():返回文件名;String getParent():返回文件所在目录名;String getPath():返回文件路径;String
5、 getAbsolutePath():返回绝对路径;boolean exists():文件是否存在;boolean canWrite():文件是否可写、读;11.2 File11.2 File类类(续续)boolean isFile():是否为文件boolean isDirectory():是否为目录;long lastModified():文件的最后修改日期;long length():返回文件的长度;boolean delete():删除文件或目录。删除成功返回true,否则返回false;boolean mkdir();创建一个目录。目录创建成功,返回true,否则返回false;Str
6、ing list():返回一个代表目录下的所有文件的字符串数组。11.2 File11.2 File类类(续续)例如:File f=new File(“datatemp.dat”);上述引用变量f调用相应的方法,得到的值:f.getName():返回 temp.datf.getParent():返回 dataf.getPath():返回 datatemp.datf.getAbsolutePath():返回 d:javadatatemp.datf.exists():若datatemp.dat文件存在返回 true,否则返回false11.2 File11.2 File类类(续续)nFile类另一
7、构造函数:public File(URI uri)使用给定的URI(uniform resource identifier,URI)对 象来定位文件。用于定位Web站点上的资源.例如,http:/ 11.3 基于基于字节字节的输入和输出类及应用实例的输入和输出类及应用实例 n抽象类InputStream和OutputStreamnFileInputStream和FileOutputStream类n随机访问文件类n过滤字节流n标准输入输出流n对象流n管道流n内存读写流n序列输入流抽象类抽象类InputStreamInputStream和和OutputStreamOutputStreamnInpu
8、tStream(输入流类)和OutputStream(输出流类),它们都是抽象类.分别声明了基于字节的输入和输出方法。nInputStreamInputStream类的方法:类的方法:read():从流中读入数据;skip():跳过数据流中指定数量的字节不读,返回值表示实际跳过的字节数;available():返回流中可用字节数;mark():在流中当前位置标记一个位置;reset():返回上一个标记过的位置,用于从这一位置读取;抽象类抽象类InputStreamInputStream和和OutputStreamOutputStream(续续)markSupport():是否支持标记和复位操作
9、;close():关闭流。nInputStreamInputStream类的方法类的方法read()read()又又提供了三种从流中读数据的提供了三种从流中读数据的方法:方法:int read():从输入流中读一个字节,形成一个0255之间的整数返回;int read(byte b):读多个字节到数组中,填满整个数组;int read(byte b,int off,int len):从输入流中读取长度为len的数据,写入数组b中从索引off开始的位置,并返回读取得字节数。对于上面的三个方法,若返回1,表明流结束。抽象类抽象类InputStreamInputStream和和OutputStrea
10、mOutputStream(续续)nOutputStreamOutputStream类的方法:类的方法:write(int b):将一个整数输出到流中(只输出低位字节,为抽象方法);write(byte b):将字节数组中的数据输出到流中;write(byte b,int off,int len):将数组b中从off指定的位置开始,长度为len的数据输出到流中;flush():刷空输出流,并将缓冲区中的数据强制送出;close():关闭流。FileInputStream FileInputStream和和FileOutputStreamFileOutputStream类类 (续续)nFileI
11、nputStream(文件输入流类)和FileOutputStream(文件输出流类)是基于字节的用于操作顺序文件的两个类。nFileInputStreamFileInputStream类:类:用于打开一个输入文件。若要打开的文件不存在,则会产生异常FileNotFoundException,这是一个非运行时异常,必须在方法中捕获或向上传递抛出异常。nFileOutputStreamFileOutputStream类类:用于打开一个输出文件。若要打开的文件不存在,则会创建一个新的文件,否则原文件的内容会被新写入的内容所覆盖。如果试图打开一个只读文件,将会引发一个 IOException异常。在
12、进行文件的读/写操作时,会产生非运行时异常IOException,必须在方法中捕获或向上传递抛出异常。FileInputStreamFileInputStream和和FileOutputStreamFileOutputStream类类(续续)n 创建输入文件流对象和输出文件流对象的的语句创建输入文件流对象和输出文件流对象的的语句:File f1=new File(“file1.txt”);/创建File对象 File f2=new File(“file2.txt”);FileInputStream in=new FileInputStream(f1);FileInputStream in=ne
13、w FileInputStream(f1);/向FileInputStream构造函数传递一个File对象 FileOutputStream out1=new FileOutputStream(f2);FileOutputStream out1=new FileOutputStream(f2);/向FileOutputStream构造函数传递一个File对象 FileOutputStream out2FileOutputStream out2=new FileOutputStream(=new FileOutputStream(“file3.txtfile3.txt”););输入流的构造函数的
14、参数是用于指定输入的文件名,输出流的构造函数参数则是用于指定输出的文件名。npublic FileOutputStreamFileOutputStream(File file,boolean append)throws FileNotFoundException Creates a file output stream to write to the file represented by the specified File object.If the second argument is true,then bytes will be written to the end of the f
15、ile rather than the beginning.A new FileDescriptor object is created to represent this file connection.First,if there is a security manager,its checkWrite method is called with the path represented by the file argument as its argument.If the file exists but is a directory rather than a regular file,
16、does not exist but cannot be created,or cannot be opened for any other reason then a FileNotFoundException is thrown.Parameters:file-the file to be opened for writing.append-if true,then bytes will be written to the end of the file rather than the beginning Throws:FileNotFoundException-if the file e
17、xists but is a directory rather than a regular file,does not exist but cannot be created,or cannot be opened for any other reason SecurityException-if a security manager exists and its checkWrite method denies write access to the file.FileInputStreamFileInputStream和和FileOutputStreamFileOutputStream类
18、类(续续)例例10-1 10-1 基于字节流的基于字节流的顺序文件的读写。顺序文件的读写。完成将一文件file1.txt的内容拷贝生成另一新文件file2.txt。package filestream;import java.io.*;class filestream public static void main(String args)try File inFile=new File(file1.txt);File outFile=new File(file2.txt);FileInputStream fis=new FileInputStream(inFile);FileOutputSt
19、ream fos=new FileOutputStream(outFile);int c;while(c=fis.read()!=-1)fos.write(c);fis.close();fos.close();catch(FileNotFoundException e)System.out.println(FileStreamsTest1:+e);catch(IOException e)System.err.println(FileStreamsTest2:+e);随机访问文件类随机访问文件类n随机文件可将每个连续的读写请求定位到文件的任何部随机文件可将每个连续的读写请求定位到文件的任何部分分
20、类nRandomAccessFile可用于随机文件的读写。它直接继承它直接继承objectobject,并且同时实现了接口,并且同时实现了接口DataInputDataInput和和DataOutputDataOutput。nDataInputDataInput接口接口中描述了用于从输入流中读取基本类型值的的一组方法,即从输入流中成组地读取字节,并将其视为基本类型值。nDataOutputDataOutput接口接口中描述了将基本类型值写入输出流中的的一组方法。随机访问文件类随机访问文件类(续续)n类类RandomAccessFileRandomAccessFile提供了支持随机文件操作的方法
21、有:提供了支持随机文件操作的方法有:XXX ReadXXX()XXX ReadXXX():XXXXXX对应基本数据类型对应基本数据类型。如如:int readInt():int readInt()、long readLong()long readLong()、byte readByte()byte readByte()、char readChar()char readChar()、unsignedByte readUnsignedByte()unsignedByte readUnsignedByte()等;等;void writeXXX()void writeXXX():XXXXXX对应基本数
22、据类型。对应基本数据类型。如如:writeInt:writeInt、writeLongwriteLong、writeBytewriteByte等等;String ReadLine():String ReadLine():从输入流中读取下一行;从输入流中读取下一行;int skipBytes(int n)int skipBytes(int n):将指针向下移动:将指针向下移动n n个字节个字节;long length()long length():返回文件长度:返回文件长度;long getFilePointer()long getFilePointer():返回指针当前位置:返回指针当前位置;
23、void seek(long pos)void seek(long pos):将指针调到所需位置。:将指针调到所需位置。随机访问文件类随机访问文件类(续续)n在生成一个随机文件对象时,构造函数的参数,除了要在生成一个随机文件对象时,构造函数的参数,除了要指明指明File对象或文件名之外,还需要指明访问文件的模式。对象或文件名之外,还需要指明访问文件的模式。例如:File f=new File(“file.txt”);new RandomAccessFile(f,“r”);new RandomAccessFile(f,“rw”);new RandomAccessFile(“file1.txt”,
24、“w”);new RandomAccessFile(“file2.txt”,“rw”);其中:“r”是只读模式,“w”是仅允许写模式,“rw”是可读可写模式。例例11-211-2随机文件的读写随机文件的读写例例11-2 11-2 随机文件的读写随机文件的读写 将整型数组中的10个数写入随机文件名temp.dat中,并以与写入顺序相反的次序从此文件中读入数据,显示在屏幕上。import java.io.*;public class random_file public static void main(String args)int data_arr=12,31,56,23,27,1,43,65
25、,4,99;try File f=new File(temp.dat);RandomAccessFile randf=new RandomAccessFile(f,rw);for(int i=0;i=0;i-)randf.seek(i*4);System.out.println(randf.readInt();randf.close();catch(IOException e)System.out.println(File access error:+e);11.3.4 11.3.4 过滤字节流过滤字节流n过滤字节流类:FilterInputStream和FilterOutputStream分
26、别对其他输入/输出流(缓冲流、数据流等)进行特殊处理。过滤仅仅意味着可以提供更多的功能,诸如缓冲、监视行数或将数字字节结合成有意义的基本数据类型,它们在读/写数据的同时可以对数据进行特殊处理,另外还提供了同步机制,使得某一时刻只有一个线程可以访问一个输入/输出流。nFilterInputStream和FilterOutputStream都是抽象类,因此由它们的子类提供额外的功能。过滤字节流过滤字节流(续续)1.1.带缓冲的过滤字节流带缓冲的过滤字节流 2.2.数据过滤流数据过滤流 3.3.其他过滤流其他过滤流1、带缓冲的过滤字节流n类类BufferedInputStreamBufferedIn
27、putStream(FilterInputStreamFilterInputStream的子类)和的子类)和BufferedOutputStreamBufferedOutputStream(FilterOutputStreamFilterOutputStream的的子类)的的子类)提供了缓冲机制,把任意的I/O流“捆绑”到缓冲流上,可以提供该I/O流的读取效率。n通过构造函数创建缓冲字节流时,除了要将缓冲流与I/O流相连接之外,还可以指定缓冲区的大小。缺省时用32字节大小的缓冲区.1、带缓冲的过滤字节流(续续)例如:FileInputStream FileInputStream inin=ne
28、w FileInputStream(=new FileInputStream(“file1.txtfile1.txt”););FileOutputStream FileOutputStream outout=new FileOutputStream(=new FileOutputStream(“file2.txtfile2.txt”););BufferedInputStream BufferedInputStream binbin=new BufferedInputStream(=new BufferedInputStream(inin,256),256)BufferedOutputStrea
29、m bout=new BufferedOutputStream(BufferedOutputStream bout=new BufferedOutputStream(outout,256);,256);int len;int len;byte bArray=new byte256;byte bArray=new byte256;len=len=binbin.read(bArray);/len.read(bArray);/len输入长度输入长度,bArray,bArray数据数据 对于BufferedOutputStream,只有缓冲区满时,才会将数据真正送到输出流,但可以使用flush()方法
30、人为地将尚未填满的缓冲区中的数据送出。2.2.数据过滤流数据过滤流n数据过滤流类DataInputStream和DataOutputStream实现了接口DataInput和DataOutput.与RandomAccessFile类似,也属于过滤字节流,但为顺序流。n利用类利用类DataInputStream和和DataOutputStream处理处理字节或字节数组;实现对文件的基本数据类型的数值的字节或字节数组;实现对文件的基本数据类型的数值的读写。读写。n提供的读写方法:read()、readInt()、readByte()、writeChar()、writeBoolean()、write
31、()等。2.2.数据过滤流数据过滤流(续续)n通过构造函数创建数据流时,要将缓冲流与I/O流相连接。创建数据流的例子如下:FileInputStream fis=new FileInputStream(file1.txt);FileInputStream fis=new FileInputStream(file1.txt);FileOutputStream fos=new FileOutputStream(file2.txt);FileOutputStream fos=new FileOutputStream(file2.txt);DataInputStream dis=new DataInp
32、utStream(fis);DataInputStream dis=new DataInputStream(fis);DataOutputStream dos=new DataOutputStream(fos);DataOutputStream dos=new DataOutputStream(fos);2.2.数据过滤流数据过滤流(续续)例例 11-3 11-3 利用利用数据过滤流读写顺序文件数据过滤流读写顺序文件 先创建输出数据过滤流,并将输出文件流和输出数据过滤流相连接;向输出数据流顺序写入8个基本类型的数据后,关闭输出数据过滤流(因为是顺序流)。接着,先创建输入数据过滤流,并将输入文件
33、流和输入数据过滤流相连接;从输入数据流顺序读取8个基本类型的数据送显示器显示后,关闭输入数据过滤流。import java.io.*;/datainput_output.javaclass datainput_output public static void main(String args)throws IOException FileOutputStream fos=new FileOutputStream(a.txt);DataOutputStream dos=new DataOutputStream(fos);try dos.writeBoolean(true);dos.writeB
34、yte(byte)123);dos.writeChar(J);dos.writeDouble(3.141592654);dos.writeFloat(2.7182f);dos.writeInt(1234567890);dos.writeLong(998877665544332211L);dos.writeShort(short)11223);finally dos.close();FileInputStream fin=new FileInputStream(a.txt);DataInputStream sin=new DataInputStream(fin);try System.out.p
35、rintln(sin.readBoolean();System.out.println(sin.readByte();System.out.println(sin.readChar();System.out.println(sin.readDouble();System.out.println(sin.readFloat();System.out.println(sin.readInt();System.out.println(sin.readLong();System.out.println(sin.readShort();finally sin.close();3.3.其他过滤流其他过滤流
36、n LineNumberInputStream:主要用于对文本文件的处理,提供了行号控制功能。n PushBackInputStream:在编译程序的词法分析阶段,经常要超前读入一个字节以界定当前词的属性,然后再将该字节退回(因为词法分析下面的处理可能还会用到该字节)。PushBackInputStream就提供了这样的能力,它提供了一个方法将刚刚读入的字节退回到输入流中去。n PrintStream:其作用是将Java语言中的不同类型的数据以字符表示形式输出到相应的输出流中去。标准输入输出流标准输入输出流n标准输入/输出处理由包java.lang 中提供的类System实现。在程序开始执行时
37、,Java会自动创建3个与设备关联的六对象:System.in、System.out和System.err对象。nSystem.inSystem.in对象对象(标准输入流对象)是从InputStream中继承而来,用于从标准输入设备中获取输入数据(通常是键盘)。nSystem.outSystem.out对象对象(标准输出流对象)是从PrintStream中继承而来,把输出送到缺省的显示设备(通常是显示器)。nSystem.errSystem.err(标准错误流对象),也是从PrintStream中继承而来,把错误信息送到缺省的显示设备(通常是显示器)。标准输入输出流标准输入输出流(续续)n S
38、ystem System类含有标准输入流的静态成员变量类含有标准输入流的静态成员变量inin,我们可以,我们可以调用它的调用它的readread方法来读取键盘数据。方法来读取键盘数据。例例 11-4 11-4 利用标准输入输出流,利用标准输入输出流,从键盘输入一行字符串从键盘输入一行字符串并显示在屏幕上。并显示在屏幕上。import java.io.*;public class ReadFromKeyboard /ReadFromKB.java public static void main(String args)try byte bArray=new byte24;String str;S
39、ystem.out.print(Enter something Using Keyborad:);System.in.read(bArray);str=new String(bArray,0,bArray.length);System.out.print(You entered:);System.out.println(str);catch(IOException ioe)System.out.println(ioe.toString();对象流对象流n对象流对象流类类ObjectOutputStreamObjectOutputStream和和ObjectInputStreamObjectIn
40、putStream分别实分别实现了接口现了接口ObjectOutputObjectOutput和和ObjectInputObjectInput,并且能够在文件,并且能够在文件(或其它类型的流)中读取和写入一个完整的对象。(或其它类型的流)中读取和写入一个完整的对象。n对象的持续性(persistence):能将对象的状态记录能将对象的状态记录,以便以便将来再生的能力将来再生的能力,叫对象的持续性。叫对象的持续性。n对象的可串行化(Serialization)是指对象通过写出描述指对象通过写出描述自己状态的的数值来记录自己的过程。自己状态的的数值来记录自己的过程。串行化的主要任务是写出对象实例变
41、量的数值。所有基本类型的变量都是可串行化的,如果变量是另一个对象的引用,则引用的对象也要可串行化。这个过程是递归的。对象流对象流(续续)n在java中,只有可串行化的对象才能通过对象流进行传输。只有可串行化的对象才能通过对象流进行传输。只有实现只有实现SerializableSerializable接口的类才能被串行化,接口的类才能被串行化,Serializable接口是一个标记接口(tagging interface),该接口不包含任何方法。当一个类声明实现Serializable接口时,只是表明该类加入对象串行化协议n建立对象输入流时,通常将建立对象输入流时,通常将FileInputStr
42、eamFileInputStream对象封装在类对象封装在类ObjectInputStreamObjectInputStream中,用中,用readObject()readObject()方法直接从输入流方法直接从输入流中读取一个对象,此方法的返回类型为中读取一个对象,此方法的返回类型为ObjectObject,往往要转,往往要转换成当初写入时的对象类型。换成当初写入时的对象类型。n建立对象输出流时,通常将建立对象输出流时,通常将FileOutputStreamFileOutputStream对象封装在对象封装在类类ObjectOutputStream,ObjectOutputStream,用
43、用writeObject()writeObject()方法可以直接将方法可以直接将对象对象 写入到输出流中。写入到输出流中。对象流对象流(续续)例例 11-5 11-5 使用对象流,使用对象流,对顺序文件进行读写。对顺序文件进行读写。程序由两个类Student.java和ObjectSeriWrite.java组成。学生类Student包含信息学号、姓名、年龄和所在系,含有一个构造函数和一个显示学生信息的方法。类Student实现了Serializable接口,是一个可串行化的类,该类的对象是一个可串行化的对象。import java.io.Serializable;public class
44、Student implements Serializable int id;String name;int age;String departmernt;public Student(int id,String name,int age,String departmernt)this.id=id;this.name=name;this.age=age;this.departmernt=departmernt;void show()System.out.println(id+,+name+,+age+,+departmernt);import java.io.*;class ObjectSer
45、iWrite public static void main(String args)Student stu1=new Student(200501,Li Ming,16,Compute Science);Student stu2=new Student(200502,Zhang Bi,17,Chineses);try FileOutputStream fo=new FileOutputStream(student.dat);ObjectOutputStream so=new ObjectOutputStream(fo);so.writeObject(stu1);so.writeObject(
46、stu2);so.close();FileInputStream fi=new FileInputStream(student.dat);ObjectInputStream si=new ObjectInputStream(fi);stu1=(Student)si.readObject();stu2=(Student)si.readObject();stu1.show();stu2.show();catch(Exception e)System.out.println(e);管道流管道流n 管道是用来把一个程序、线程和代码块的输出连接到另一管道是用来把一个程序、线程和代码块的输出连接到另一个程
47、序、线程和代码块的输入个程序、线程和代码块的输入。java.io中提供了类PipedInputStream和PipedOutputStream作为管道的输入/输出流。n管道输入流作为一个通信管道的接收端,管道输出流则作为发送端。管道流必须是输入输出并用,即在使用管道前,两者必须进行连接。管道输出流管道输入流图11-3管道流管道流管道流(续续)n 管道输入/输出流可以用两种方式进行连接:(1)在构造方法中进行连接:PipedInputStream(PipedOutputStream pos);PipedOutputStream(PipedInputStream pis);(2)通过各自的conn
48、ect()方法连接:在类PipedInputStream中,调用方法:connect(PipedOutputStream pos);在类PipedOutputStream中,调用方法:connect(PipedInputStream pis);管道流管道流(续续)例例 11-11-将数据从输出管道进,从输入管道出将数据从输出管道进,从输入管道出 程序将两个byte型数据从输出管道进去,从从输入管道出来,并显示出来。import java.io.*;class pipedstream public static void main(String args)throws IOException b
49、yte aByteData1=123,aByteData2=111;PipedInputStream pis=new PipedInputStream();PipedOutputStream pos=new PipedOutputStream(pis);System.out.println(PipedInputStream);try pos.write(aByteData1);pos.write(aByteData2);System.out.println(byte)pis.read();System.out.println(byte)pis.read();finally pis.close(
50、);pos.close();内存读写流内存读写流njava.io中提供了类ByteArrayInputStream、ByteArrayOutputStream和StringBufferInputStream以支持 内存的读/写。ByteArrayInputStream可以从指定的字节数组中读取数据。ByteArrayOutputStream中提供了缓冲区可以存放数据(缓冲区大小可以在构造方法中设定,缺省为32),可以用write()方法向其中写入数据,然后用toByteArray()方法将缓冲区中的有效字节写到字节数组中去。nStringBufferInputStream与ByteArrayI