java 程序设计 第9章.ppt
第第9章章流式输入输出与文件处理流式输入输出与文件处理9.1输入输出基本概念输入输出基本概念9.2面向字节的输入输出面向字节的输入输出9.3面向字符的输入输出面向字符的输入输出9.4文件处理文件处理9.5对象串行化对象串行化9.1.1I/O设备与文件设备与文件1.I/O设备分类设备分类存储设备存储设备存储设备包括硬盘、软盘、光盘等,存储设备包括硬盘、软盘、光盘等,输入输入/输出设备输出设备输入设备有键盘、鼠标、扫描仪等输入设备有键盘、鼠标、扫描仪等输出设备有显示器、打印机、绘图仪等。输出设备有显示器、打印机、绘图仪等。2.文件的分类文件的分类根据数据的组织方式分为根据数据的组织方式分为文本文件文本文件-存放的是存放的是ASCII码(或其它编码)表示的字符码(或其它编码)表示的字符二进制文件二进制文件-具有特定结构的数据。具有特定结构的数据。9.1.2流的概念流的概念1.流的定义流的定义流是在计算机的输入输出操作中流动的数据系列流是在计算机的输入输出操作中流动的数据系列输出流是往存储介质或数据通道中写入数据输出流是往存储介质或数据通道中写入数据输入流是从存储介质或数据通道中读取数据输入流是从存储介质或数据通道中读取数据流的特性与分类流的特性与分类2.流的特性流的特性先进先出。先进先出。顺序存取。顺序存取。只读或只写。只读或只写。3.Java流的处理分类流的处理分类面向字节的流,数据的处理是以字节为基本单位;面向字节的流,数据的处理是以字节为基本单位;面向字符的流,用于字符数据的处理。面向字符的流,用于字符数据的处理。4.Java系统预定义的流对象系统预定义的流对象标准输入(标准输入(System.in):):InputStream类型,通常代表键盘输入;类型,通常代表键盘输入;标准输出(标准输出(System.out):):PrintStream类型,通常写往显示器;类型,通常写往显示器;标准错误输出(标准错误输出(System.err):):PrintStream类型,通常类型,通常写往显示器。写往显示器。标准输入输出在实际运行时的具体目标对象也可能变化,标准输入输出在实际运行时的具体目标对象也可能变化,System类中提供了如下方法重新设置标准流对象:类中提供了如下方法重新设置标准流对象:staticvoidsetIn(InputStreamin):重新定义标准输入流:重新定义标准输入流staticvoidsetErr(PrintStreamerr):重新定义标准错误输出:重新定义标准错误输出staticvoidsetOut(PrintStreamout):重新定义标准输出:重新定义标准输出1面向字节的输入流的类继承层次面向字节的输入流的类继承层次9.2面向字节的输入面向字节的输入/输出流输出流2、类类InputStream介绍介绍publicintread():读一个字节:读一个字节publicintread(byteb):读多个字节到字节数组:读多个字节到字节数组publicintread(byteb,intoff,intlen):从输入流从输入流读指定长度的数据到字节数组,数据从字节数组读指定长度的数据到字节数组,数据从字节数组的的off处开始存放。处开始存放。publiclongskip(longn):指针跳过:指针跳过n个字节,定个字节,定位输入位置指针的方法位输入位置指针的方法publicvoidmark():在当前位置指针处做一标记:在当前位置指针处做一标记publicvoidreset():将位置指针返回标记处:将位置指针返回标记处publicvoidclose():关闭流:关闭流3类类InputStream的子类的使用的子类的使用类名 构造方法的主要参数 功能描述 ByteArrayInputStream 字节数组 以程序中的一个字节数组作为输入源,通常用于对字节数组中的数据进行转换。FileInputStream 类File的对象或字符串表示的文件名 以文件作为数据源,用于实现对磁盘文件中数据的读取。PipedInputStream PipedOutputStream的对象 与另一输出管道相连,读取写入到输出管道中的数据,用于程序中线程间通信 3类类InputStream的子类的使用(续表)的子类的使用(续表)FilterInputStream InputStream的对象 用于装饰另一输入流以提供对输入数据的附加处理功能,子类见表9-2 SequeueInputStream 一系列InputStream的对象 将两个其他流首尾相接,合并为一个完整的输入流。ObjectInputStream InputStream的对象 用于从输入流读取串行化对象。可实现轻量级对象持久性。4、类、类FilterInputStream的常见子类的常见子类类名类名 功能描述 BufferedInputStream 为所装饰的输入流提供缓冲区的功能,以提高输入数据的效率 DataInputStream 为所装饰的输入流提供数据转换的功能,可从数据源读取各种基本类型的数据。LineNumberInputStream 为文本文件输入流附加行号 PushbackInputStream 提供回压数据的功能,可以多次读同样数据 例例9-1在屏幕上显示文件内容在屏幕上显示文件内容importjava.io.*;publicclassDisplayFilepublicstaticvoidmain(Stringargs)tryFileInputStreaminfile=newFileInputStream(args0);intbyteRead=infile.read();while(byteRead!=-1)System.out.print(char)byteRead);byteRead=infile.read();catch(ArrayIndexOutOfBoundsExceptione)System.out.println(需要提供一个文件名作为命令行参数需要提供一个文件名作为命令行参数);catch(FileNotFoundExceptione)System.out.println(filenotfind!);catch(IOExceptione)数据输入流(数据输入流(DataInputStream为了实现各种基本类型数据的输入处理为了实现各种基本类型数据的输入处理实现实现DataInput接口接口readByte()readBoolean()readShort()readChar()readInt()-读整数读整数readLong()readFloat()readDouble()readUTF()-读字符串读字符串例例9-2从键盘输入一个整数,求该数的各位数字之和从键盘输入一个整数,求该数的各位数字之和importjava.io.*;publicclassBitSumpublicstaticvoidmain(Stringargs)throwsIOExceptionDataInputStreamdin=newDataInputStream(System.in);System.out.print(inputainteger:);intx=din.readInt();intsum=0;intn=x;while(n0)intlastbit=n%10;n=n/10;sum=sum+lastbit;System.out.println(x+的各位数字之和的各位数字之和=+sum);2、面向字节的输出流面向字节的输出流2、文件输入、文件输入/输出流的使用输出流的使用类类OutputStream的方法的方法publicvoidwrite(intb):将参数:将参数b的低字节写入的低字节写入输出流输出流publicvoidwrite(byteb):将字节数组全部写:将字节数组全部写入输出流入输出流publicvoidflush():强制将缓冲区数据写入输出:强制将缓冲区数据写入输出流对应的外设流对应的外设publicvoidclose():关闭输出流:关闭输出流例例9-3将一个大文件分拆为若干小文件将一个大文件分拆为若干小文件importjava.io.*;publicclassBigToSmallpublicstaticvoidmain(Stringargs)intnumber=0;finalintsize=Integer.parseInt(args1);byteb=newbytesize;tryFileInputStreaminfile=newFileInputStream(args0);while(true)FileOutputStreamoutfile=newFileOutputStream(file+number);number+;intbyteRead=infile.read(b);if(byteRead=-1)break;outfile.write(b,0,byteRead);outfile.close();catch(IOExceptione)基本数据类型数据的读写问题基本数据类型数据的读写问题类类DataOutputStream实现各种类型数据的输出处理,它实现各种类型数据的输出处理,它实现了实现了DataOutput接口接口writeByte(int)writeBytes(String)writeBoolean(boolean)writeChars(String)writeInt(int)writeLong()writeFloat(float)writeDouble(double)writeUTF(String)等。等。例例9-4找出找出10100之间的所有姐妹素数,写入到文之间的所有姐妹素数,写入到文件中。所谓姐妹素数是指相邻两个奇数均为素数件中。所谓姐妹素数是指相邻两个奇数均为素数importjava.io.*;publicclassFindSisterPrimepublicstaticbooleanisPrime(intn)for(intk=2;k=Math.sqrt(n);k+)if(n%k=0)returnfalse;returntrue;publicstaticvoidmain(Stringarguments)tryFileOutputStreamfile=newFileOutputStream(x.dat);DataOutputStreamout=newDataOutputStream(file);for(intn=11;n100;n+=2)if(isPrime(n)&isPrime(n+2)out.writeInt(n);out.writeInt(n+2);out.close();catch(IOExceptione);x.Dat文件FileOutputStreamDataOutputStream数据数据.importjava.io.*;publicclassOutSisterPrimepublicstaticvoidmain(Stringarguments)tryFileInputStreamfile=newFileInputStream(x.dat);DataInputStreamin=newDataInputStream(file);trywhile(true)intn1=in.readInt();intn2=in.readInt();System.out.println(n1+,+n2);catch(EOFExceptione)in.close();catch(IOExceptione)1、面向字符的输入流类层次、面向字符的输入流类层次9.3面向字符的输入面向字符的输入/输出流输出流表表9-4类类Reader的主要子类及说明的主要子类及说明类名 构造方法的主要参数 功能描述 CharArrayReader 字符数组char 用于对字符数组中的数据进行转换 BufferedReader 类Reader的对象 为输入提供缓冲的功能,提高效率 LineNumberReader 类Reader的对象 为输入数据附加行号 InputStreamReader InputStream的对象 将面向字节的输入流转换为字符输入流 表表9-4类类Reader的主要子类及说明(续)的主要子类及说明(续)FileReader 文件对象或字符串表示的文件名 文件作为输入源 PipedReader PipedWriter的对象 与另一输出管道相连,读取另一管道写入的字符 StringReader 字符串 以程序中的一字符串作为输入源,通常用于对字符串中的数据进行转换 LineNumberReader类的使用类的使用例例9-5从一个文本文件中读取数据加上行号后显示。从一个文本文件中读取数据加上行号后显示。importjava.io.*;publicclassAddLineNopublicstaticvoidmain(Stringargs)tryFileReaderfile=newFileReader(AddLineNo.java);LineNumberReaderin=newLineNumberReader(file);booleaneof=false;while(!eof)Stringx=in.readLine();if(x=null)/是否读至文件尾是否读至文件尾eof=true;elseSystem.out.println(in.getLineNumber()+:+x);in.close();catch(IOExceptione);例例9-6例例9-5(续)(续)2、面向字符的输出流类层次面向字符的输出流类层次表9-5类Writer的主要子类及说明类名 构造方法的主要参数 功能描述 CharArrayWriter 字符数组char 用于对字符数组中的数据进行转换 BufferedWriter 类Writer的对象 为输出提供缓冲的功能,提高效率 InputStreamWriter OutputStream的对象 将面向字节的输出流转换为字符输出流 FileWriter 文件对象或字符串表示的文件名 文件作为输出源 表9-5类Writer的主要子类及说明(续)PipedWriter PipedReader的对象 与另一输出管道相连,写入数据给另一管道供其读取 StringWriter 字符串 以程序中的一字符串作为输出源,用于对字符数组中的数据进行转换 FilterWriter Writer的对象 装饰另一输出流以提供附加的功能 PrinterWriter Writer的对象或OutputStream的对象 为所装饰的输出流提供打印输出,与类PrintStream只有细微差别。例例9-6用用FileWriter流将流将ASCII英文字符集字符英文字符集字符写入到文件写入到文件importjava.io.*;publicclassCharWritepublicstaticvoidmain(Stringargs)tryFileWriterfw=newFileWriter(charset.txt);for(inti=32;i0)for(inti=0;iargs.length;i+)fileToCheck=newFile(argsi);info(fileToCheck);elseSystem.out.println(Nofilegiven.);publicstaticvoidinfo(Filef)throwsIOExceptionSystem.out.println(Name:+f.getName();System.out.println(Path:+f.getPath();System.out.println(AbsolutePath:+f.getAbsolutePath();if(f.exists()System.out.println(Fileexists.);System.out.println(andisReadable:+f.canRead();System.out.println(andisWriteable:+f.canWrite();System.out.println(Fileis+f.length()+bytes.);elseSystem.out.println(Filedoesnotexist.);2.文件的顺序访问文件的顺序访问1.FileInputStream对象对象(1)利用文件名创建文件输入流利用文件名创建文件输入流newFileInputStream(/etc/motd);(2)利用文件对象创建文件输入流利用文件对象创建文件输入流2.从从FileInputStream读数据读数据intread()intread(byteb)intread(byteb,intoffset,intlen)3.关闭关闭FileInputStream注:文件输出流注:文件输出流FileOutputStream类似类似.3随机访问文随机访问文件件(1)创建随机访问文件创建随机访问文件用用文文件件名名myRAFile=newRandomAccessFile(Stringname,Stringmode);用用文文件件对对象象myRAFile=newRandomAccessFile(Filefile,Stringmode);其中,其中,mode参数决定了访问文件的权限,如只读参数决定了访问文件的权限,如只读r或读写或读写wr等。等。(2)对文件位置指针的操作对文件位置指针的操作可以使用在可以使用在DataInputStream和和DataOutputStream里出现的所有里出现的所有read()和和write()函函数。数。还有几个函数帮助你在文件里移动指针:还有几个函数帮助你在文件里移动指针:longgetFilePointer();返回当前指针返回当前指针voidseek(longpos);将文件指针定位到一个绝将文件指针定位到一个绝对地址。地址是相对于文件头的偏移量。地址对地址。地址是相对于文件头的偏移量。地址0表示文件的开头。表示文件的开头。longlength();返回文件的长度。返回文件的长度。1、对象输入流和对象输出流、对象输入流和对象输出流writeObject()和()和readObject()方法实现了对象的串行化方法实现了对象的串行化(Serialized)和反串行化)和反串行化(Deserialized)例例9-11系统对象的串行化处理系统对象的串行化处理程序程序1:将系统对象写入文件:将系统对象写入文件importjava.io.*;importjava.util.*;publicclasswritedatepublicstaticvoidmain(Stringargs)tryObjectOutputStreamout=newObjectOutputStream(newFileOutputStream(storedate.dat);out.writeObject(newDate();out.writeObject(helloworld);System.out.println(写入完毕写入完毕);catch(IOExceptione)程序程序2:读取文件中的对象并显示出来:读取文件中的对象并显示出来importjava.io.*;importjava.util.*;publicclassreaddatepublicstaticvoidmain(Stringargs)tryObjectInputStreamin=newObjectInputStream(newFileInputStream(storedate.dat);Datecurrent=(Date)in.readObject();System.out.println(日期:日期:+current);Stringstr=(String)in.readObject();System.out.println(字符串字符串:+str);catch(IOExceptione)catch(ClassNotFoundExceptione)3、用户定义类的对象串行化、用户定义类的对象串行化例例9-12利用对象串行化将各种图形元素以对象形式利用对象串行化将各种图形元素以对象形式存储,从而实现图形的保存。存储,从而实现图形的保存。程序程序1:图形对象的串行化设计:图形对象的串行化设计importjava.awt.Graphics;abstractclassGraphimplementsSerializable/抽象类抽象类publicabstractvoiddraw(Graphicsg);/定义定义draw方法方法classLineextendsGraphimplementsSerializableintx1,y1;intx2,y2;publicvoiddraw(Graphicsg)g.drawLine(x1,y1,x2,y2);publicLine(intx1,inty1,intx2,inty2)this.x1=x1;this.y1=y1;this.x2=x2;this.y2=y2;classCircleextendsGraphimplementsSerializableintx,y;intr;publicvoiddraw(Graphicsg)g.drawOval(x,y,r,r);publicCircle(intx,inty,intr)this.x=x;this.y=y;this.r=r;程序程序2:测试将图形对象串行化写入文件:测试将图形对象串行化写入文件importjava.io.*;publicclassWriteGraphpublicstaticvoidmain(Stringa)Linek1=newLine(20,20,80,80);Circlek2=newCircle(60,50,80);tryObjectOutputStreamout=newObjectOutputStream(newFileOutputStream(“storedate.dat”);out.writeObject(newInteger(2);out.writeObject(k1);out.writeObject(k2);catch(IOExceptione)System.out.println(e);程序程序3:对串行化图形对象的访问并绘制图形:对串行化图形对象的访问并绘制图形importjava.awt.*;importjava.io.*;publicclassDisplayGraphextendsFramepublicstaticvoidmain(Stringa)newDisplayGraph();publicDisplayGraph()super(读对象文件显示图形读对象文件显示图形);setSize(300,300);setVisible(true);Graphicsg=getGraphics();tryObjectInputStreamin=newObjectInputStream(newFileInputStream(storedate.dat);intn=(Integer)in.readObject().intValue();for(inti=1;i=n;i+)Graphme=(Graph)in.readObject();me.draw(g);catch(IOExceptione)System.out.println(e);catch(ClassNotFoundExceptione)System.out.println(e);调用对象的方法绘图调用对象的方法绘图