-83-第4章输入与输出流通过本章的学习了解Java语言中流的基本概念,掌握与输入与输出流有关的类及简单应用。通过技能训练,掌握在Java程序中实现多种输入输出操作的技能。4.1System类与流的概念System类是Java语言中一个功能强大、非常有用的类,它提供了标准输入/输出及运行时的系统信息。从System类不能创建对象,也就是说,System类的所有属性和方法都是静态的,引用时要以System作为前缀。System.in与System.out是System类的两个静态属性,分别对应了系统的标准输入/输出流。标准输入/输出一共有三个标准流,由java.lang.System类管理。在System类中,标准输入/输出流是按如下格式定义的:publicfinalclassjava.lang.Systemextendsjava.lang.Object{publicstaticInputStreamin;publicstaticPrintStreamout;publicstaticPrintStreamerr;}其中,System.in称为标准输入流,用于程序输入,通常读取用户从键盘输入的信息;System.out称为标准输出流,用于程序输出,通常向用户显示信息;System.err称为标准错误流,用于向用户显示出错信息。标准输出流定义了向屏幕输出不同类型数据的方法print()和println()。println()方法的一般语法格式可以概括如下:publicvoidprintln(类型变量或对象);(1)println()方法的功能是向屏幕输出其参数指定的变量或对象,然后再换行,使光标停留在屏幕的下一行的第一个字符位置。如果println()方法的参数为空,则将输出一个空行。(2)println()方法可以输出包括boolean,double,float,int,long类型在内的变量以及所有系统类和用户自定义类的对象。(3)print()方法的语法格式与功能println()方法完全相同,不同的是print()方法输出对象之后并不附带一个回车,下一次输出时将输出在同一行中。标准输入流包含了从键盘获取的输入信息,通过如下格式实现:-84-System.in.方法;当用户从键盘读入数据时,主要通过read()方法来实现。read()方法有三种使用格式:read();//从输入流读入一个字节read(byte[]);//把指定个数的字节数据读入到一个字节数组中read(byte[],intoff,intlen)//把len个字节的数据读入到一个字节数组中一个程序在运行时通常要和外部设备交互,即从外部设备获取信息或向外部设备发送信息,这就是所谓的输入/输出(I/O)操作。在Java语言中,输入/输出都是通过流(Stream)来完成的,这样程序无论是要进行输入还是输出,只要针对流进行操作就可以了。简单地说,流就是指在计算机与输入/输出之间流动的数据序列。序列中的数据既可以是二进制数据,也可以是其他符合某种格式规定的特定数据,如字符流序列等。Java语言定义了字节流和字符流两种类型,并通过字节流类和字符流类实现输入/输出操作。4.2字节流类字节流提供了处理字节的输入/输出方法,如在读写二进制数据时就要使用字节流。在Java语言中,字节流类用两个类层次定义,在顶层的是两个抽象类:InputStream(输入流)和OutputStream(输出流)。这两个抽象类派生出来的具体子类提供了读写各种不同设备如磁盘文件的功能。4.2.1字节输入流类字节输入流类的作用就是从外部设备获取字节数据到计算机内存中。在编写应用程序时,常常需要定义字节输入流类的子类以及方法,才能够实现字节输入功能。表4.1列出了字节输入流类派生的子类。表4.1字节输入流的子类名称功能AudioInputStream读取声音字节流ByteArrayInputStream读取输入流到内存缓冲区FileInputStream读取文件输入流FilterInputStream建立可过滤的输入流ObjectInputStream读取对象并可以进行还原PipedInputStream建立输入流管道连接到输出流SequenceInputStream建立顺序输入流并逐个读取表4.1中的FilterInputStream称为字节过滤输入流,是一个常用的字节输入流类,它把另一个输入流作为流的来源。字节过滤输入流本身是一个抽象类,不能由它创建对象。这个子类的功能又是通过它的4个子类来实现的,主要是为已有的某个输入流提供附加处理功能。例如,用来设置或查询读取行数,把已读取的某个字节再退回去等,从而起到所谓的过滤作用。表-85-4.2列出了字节过滤输入流派生的子类。表4.2字节过滤输入流的子类名称功能DataInputStream提供一些基于多字节的读取方法,从而可以读取基本类型的数据PushInputStream建立一种特殊的过滤流,它能提供把已读取的一个字节退回到输入流中去的方法BufferedInputStream为其他输入流增加功能,能够提高读取速度LineNumberInputStream建立带有行计数功能的过滤输入流表4.3列出了抽象类InputStream中的方法,所有这些方法在发生错误时都会抛出IOException异常,而且这个抽象类定义的方法都可以被它们所有的子类继承使用。表4.3字节输入流的主要方法名称功能intread()读取输入流的下一个字节,返回读入的字节数intread(byteb[])将输入流读到字节数组中,返回读入的字节数intread(byteb[],intoff,intlen)将输入流向字节数组的off处读取len个字节,返回读入的字节数longskip(longn)从输入流中跳过n个字节,返回跳过的字节数abstractvoidclose()关闭输入流,释放资源【例4.1】接收键盘输入的字符串,并显示到屏幕上。importjava.io.*;//引入输入/输出程序包publicclassGetInputStream//定义用户类{publicstaticvoidmain(Stringargs[]){intcount;//定义读入字符数的变量byteinput[]=newbyte[256];//定义存放字节数据的数组StringInputString;DataInputStreamstdin=newDataInputStream(System.in);//从键盘读取输入BufferedInputStreambufin=newBufferedInputStream(stdin);//创建输入缓冲区try{System.out.print(请输入字符串,结束请按Enter...\n+==);count=bufin.read(input);//使用了表4.3中的第2种方法System.out.println(读入的字符数目:+count);InputString=newString(input,0,count);System.out.print(输入的字符串为:+InputString);stdin.close();bufin.close();}catch(IOExceptione){System.out.println(发生I/O异常!);-86-}}}程序运行结果如下:请输入字符串,结束请按Enter...==北方电子工业有限公司读入的字符数目:22输入的字符串为:北方电子工业有限公司本例中使用了try——catch异常处理结构,try语句块中是一些可能产生异常的语句,catch语句块中是一些用来处理异常的语句。当try语句块中的相关语句产生异常时,catch语句块会捕捉这个异常,并输出发生I/O异常!的提示信息。异常处理的有关内容详见第6章。该例中的第1行importjava.io.*;是Java语言进行与输入输出操作有关的编程时需要导入的程序包,本章所涉及的类大都包含在该程序包中。程序中在DataInputStream类的构造方法中指定参数为“System.in”,表示要从键盘读取用户输入的数据,创建BufferedInputStream类的对象则是用来提高输入输出的执行效率。在Java语言应用程序中,经常会用到DataInputStream类和BufferedInputStream类的构造方法以完成输入操作。DataInputStream类提供的构造方法如下:DataInputStream(InputStreamin);参数in为底层输入流,通常与一个具体的设备相关联。该方法的功能是建立一个新的数据输入流以从指定的输入流读数据。BufferedInputStream类提供的构造方法如下:(1)publicBufferedInputStream(InputStreamin);参数in为底层输入流,通常与一个具体的设备相关联。该方法的功能是创建一个缓冲输入流并保存在参数in中供以后使用。同时也建立起来一个缓冲数组并保留在buf中(buf是缓冲输入流类的成员变量,是一个字节类型的数组,用于存储数据的内部缓冲区,在需要时它可以被另一个不同大小的数组替代)。(2)publicBufferedInputStream(InputStreamin,intsize);参数in为底层输入流,通常与一个具体的设备相关联,size为缓冲区大小。该方法的功能是以指定的缓冲区大小创建一个缓冲输入流,并保存在参数in中供以后使用。一个长度为size的内部缓冲区数组也建立起来并保存在buf中。4.2.2字节输出流类字节输出流类的作用就是将暂存在计算机内存中的数据输出到外部设备。在编写应用程序时,常常需要定义字节输出流类的子类以及方法,才能够实现字节输出功能。表4.4列出了字节输出流类派生的子类。-87-表4.4字节输出流的子类名称功能ByteArrayOutputStream将字节数据写入缓冲区FileOutputStream写入文件输出流FilterOutputStream建立可过滤的输出流ObjectOutputStream将对象原始数据类型写入输出流PipedOutputStream建立输出流管道连接到输入流表4.4中的FilterOutputStream称为字节过滤输出流,它本身是一个抽象类,不能由它创建对象。这个子类的功能又是通过它的3个子类来实现的。这里的过滤,就是指将缓冲、打印转变为某种数据形式等的附加处理操作。表4.5列出了字节过滤输出流派生的子类。表4.5字节过滤输出流的子类名称功能DataOutputStream对这个过滤数据输出流可以写入任何符合Java数据类型的信息,这些信息可以被该类的方法读取BufferedOutputStream为输出流提供缓冲式过滤流,缓冲区大小可以通过入口参数指定,也可以固定为512字节PrintStream建立一个打印输出流,把符合Java数据类型的信息打印出来表4.6列出了抽象类OutputStream中的方法,所有这些方法在发生错误时都会抛出IOException异常,而且这个抽象类定义的方法都可以被它们所有的子类继承使用。表4.6字节输出流的主要方法名称功能Voidwrite(intb)将整数b的低8位写入输出流Voidwrite(byteb[])将字节数组写入输出流Voidwrite(byteb[],intoff,intlen)从字节数组的off处向输出流写入len个字节abstractvoidflush()强制将输出流保存在缓冲区中的数据写入终点abstractvoidclose()先调用flush然后关闭输出流,释放资源【例4.2】接收键盘输入的内容,并通过字节输出流输出到屏幕上。importjava.io.*;publicclassGetOutputStream{publicstaticvoidmain(Stringargs[]){intcount;byteinput[]=newbyte[256];St