您好,欢迎访问三七文档
第12章文件和流输入和输出是一个程序必备的功能,Java的应用程序和JavaApplet往往经常要通过输入和输出来读写数据。本章将介绍如何从一个能发送字节或字符序列的“数据源”获得输入,以及如何将输出发送给能够接收字节序列的一个“目标”。字节序列的数据源及目标可以是文件,也可以是一个网络连接,甚至是一个内存块。在本章中,将重点讨论用来操控文件的方法,以及用来将数据(可以是对象)实际写入文件、将信息从文件中读回的方法,或者是更新文件的方法。12.1Java流类库简介Java语言的输入输出功能是十分强大而灵活的,它往往需要包装许多不同的对象。在Java类库中,I/O部分的内容是很庞大的,因为它涉及的领域很广泛:标准输入输出,文件的操作,网络上的数据流,字符串流,对象流,zip文件流……本章的目的是做一个简要的介绍。12.1.1流的概念Java所有的I/O机制都是基于数据流的,这些数据流表示了字符或者字节数据的流动序列。Java的I/O流提供了读写数据的标准方法。任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法。流是一个很形象的概念,当程序需要读取数据时,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接,则这就是“输入流”,如图12-1所示。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流,这就是“输出流”,这时你就可以想像数据好像在这其中“流”动一样,如图12-2所示。图12-1输入流示意图图12-2输出流示意图Java中的流分为两种,一种是字节流,另一种是字符流,分别由四个抽象类来表示:Java语言程序设计教程第第InputStream,OutputStream,Reader,Writer。Java中其他多种多样变化的流均是由它们派生出来的,下面介绍Java的I/O库。12.1.2Java的I/O库Java中的字节流是用于处理字节的输入和输出的,包括读写二进制数据等方面的内容。而Java中的字符流则用于处理字符的输入和输出,采用的是Unicode编码,可以实现国际化。使用字符流的另外一个好处就是:字符流比字节流更有效率。1.字节流在Java中,字节流分为“输入流”和“输出流”。可以从中读出一系列字节的对象称为“输入流”(InputStream);而能向其中写入一系列字节的对象则称为“输出流”(OutputStream)。这两种对象分别是由java.io包中的抽象类InputStream和OutputStream来实现的。具体的字节流结构如图12-3和图12-4所示。从图中可以看出:1)字节流的两个顶层类是抽象类,分别是InputStream和OutputStream。2)每个抽象类都有子类来实现具体的功能,处理不同的输入和输出。InputStream和OutputStream类是不能实例化的,实际上在程序中使用就是它们的子类,如文件输入输出流FileInputStream和FileOutputStream。图12-3InputStream类结构图图12-4OnputStream类结构图表12-1是字节流的几个常用子类及功能。第第第12章文件和流表12-1字节流常用子类及功能字节流类功能简单介绍DataInputStream包含了读取Java标准数据类型的输入流DataOutputStream包含了写Java标准数据类型的输出流ByteArrayInputStream从字节数组读取的输入流ByteArrayOutputStream写入字节数组的输出流FileInputStream从文件读入的输入流FileOutputStream写入文件的输出流PrintStream包含最常见的Print()和Println()的输出流PushbackInputStream返回一个字节到输入流,主要用于编译器的实现PipedInputStream输入管道PipedOutputStream输出管道SequenceInputStream将n个输入流联合起来,一个接一个按一定顺序读取BufferInputStream缓冲输入流BufferOutputStream缓冲输出流FilterInputStream实现了InputStream接口的过滤器输入流FilterOutputStream实现了OutputStream接口的过滤器输出流字节流抽象类InputStream和OutputStream的常用方法如下。(1)InputStream1)abstractintread():读取一个字节的数据,并返回读到的字节。read方法若遇到数据流的末尾,便会返回一个–1值。2)intread(byte[]b):将数据读入一个字节数组,同时返回读回的字节数。和前面一样,如果遇到数据流的末尾,read方法会返回一个–1值。读入的最大字节数由b.length界定。3)intread(byte[]b,intoff,intlen):将数据读入一个字节数组。read会返回读回的实际字节数,或在流的结尾处返回一个–1值。其中:b:指定要把字节读入哪个数组;off:指定数组的偏移位置,第一个字节应放在哪个位置;len:读回的最大字节数。4)longskip(longn):在输入流中跳过几个字节,它返回的实际跳过的字节数(如果遇到流的末尾,这个数字则可能小于n)。5)intavailable():返回在不加阻止的情况下,可用的字节数(“阻止”是指当前线程必须暂停,等待下一次被唤醒)。6)voidclose():关闭输入流。(2)OutputStream1)abstractvoidwrite(intb):写入一个字节的数据。2)voidwrite(byte[]b):写入数组b内的所有字节。3)voidwrite(byte[]b,intoff,intlen):功能和上面的方法一样。其中:b:指定要从哪个数组写入数据;off:指定数组b的一个偏移位置,从哪个位置的字节开始写入;len:要写入的字节数量。4)voidclose():清空和关闭输出流。Java语言程序设计教程第第5)voidflush():清空输出流;换言之,将缓冲下来的所有数据都发到目的地。对于缓冲流式输出来说,write()方法所写的数据并没有直接发送到输出流的目标端,而是先暂时存放在流的缓冲区中,等到缓冲区中的数据达到一定的数量后,再一次性的向目标端写出。但在某些情况下,缓冲区中的数据不满时就需要将它写到目标端,这时就需要使用flush()方法。2.字符流同字节流类似,字符流也是通过两个顶层的抽象类Reader和Writer的子类来实现对Unicode字符(在Java中一个字符由两个字节组成)流的处理。如图12-5和图12-6所示。从图中可以看出:1)字符流的两个顶层类是抽象类,分别是Reader和Writer。2)每个抽象类都有子类来实现具体的功能,处理不同的设备的输入和输出。图12-5Reader类结构图图12-6Writer类结构图字符流的几个常用子类及功能见表12-2。表12-2字符流常用子类及功能字符流类功能简单介绍StringReader从字符串读取的输入流StringWriter写入字符串的输出流FileReader从文件读入的输入流FileWriter写入文件的输出流第第第12章文件和流(续)字符流类功能简单介绍PushbackReader返回一个字符到输入流,主要用于编译器的实现PipedReader输入管道PipedWriter输出管道CharArrayReader从字符数组读取的输入流CharArrayWriter写入字符数组的输出流BufferReader缓冲输入流BufferWriter缓冲输出流FilterReader实现了InputStream接口的过滤输入流FilterWriter实现了OutputStream接口的过滤输出流InputStreamReader将字节转换为字符的输入流OutputStreamWriter将字节转换为字符的输出流对比表12-1和表12-2,可以发现,字符流很多的类名的作用和字节流都差不多。这些方法的不同之处仅仅在于一个是针对字节的,一个是针对字符的。而且在Reader和Writer类中提供的基本方法也和InputStream和OutputStream的基本方法一样,最主要是read()和write()方法:publicabstractintread()throwsIOExceptionpublicabstractvoidwrite()throwsIOException其它的方法与InputStream和OutputStream类的那些方法类似,这里不再重复。当然,这些方法处理的是Unicode字符,而InputStream和OutputStream类的方法处理的是字节。12.2基本流Java的基本流完成程序中最基本的输入输出工作。12.2.1标准的输入和输出在Java编程环境中,标准输入和输出的概念和C/C++语言中的相似。它有3个内置的标准流对象,本书第二章已经作了介绍,它们是:标准输入流System.in、标准输出流System.out、标准出错流System.err。在前面的章节多次用到这几个对象,读者可能对这几个标准对象已很熟悉了,Java程序就是通过System.in、System.out和System.err来实现标准输入输出和标准错误输出。例12.1标准输入输出演示StdInOut.javaimportjava.io.*;publicclassStdInOut{publicstaticvoidmain(Stringargs[]){charc='a';inti,count=0;bytebuffer[]=newbyte[100];System.out.print(Inputachar:);try{c=(char)System.in.read();//输入一个字节并转化为字符cSystem.in.skip(2);//跳过输入字符后的回车}catch(IOExceptionioe){Java语言程序设计教程第第System.err.println(ioe.toString());}System.out.println(c);System.out.print(InputaString:);try{count=System.in.read(buffer);//输入若干字节到字节数组buffer}catch(IOExceptionioe){System.err.println(ioe.toString());}for(i=0;i=count-1;i++)System.out.print((char)buffer[i]);}}在这个程序中,当程序执行到read()方法时就停下来,等待用户的键盘输入;用户在输入一个字符后,需要再输入一个回车符,以保证read()可以读到这个字符。read()方法读入字符后返回int型的变量,所以需要强制的类型转换符(char)把它转换成char后再复制给char类型的变量c。由于输入操作有可能会抛出IOException异常,所以要用try-catch块进行异常处理。第二次用户同样用read()方法读入一串字符。运行效果如图12-7所示。图12-7例12.1的运行效果图12.2.2利用Java.io类库除了上述的3个对象,还可以通过java.io包中提供的流类接收键盘的输入,在程序中经常用到了前面提到的InputStreamReader、BufferReader类。InputStreamReader是字节流通向字符流的桥梁:它读取字节并将其解码为字符。每次调用InputStreamReader中的一个read()方法都会导致从基本输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从基本流读取多个字节,这就需要BufferReader来设立缓冲区,然后用readLine()方法读入一行字符,方法如下:InputStreamReaderisr=ne
本文标题:第12章文件和流
链接地址:https://www.777doc.com/doc-2242693 .html