[计算机硬件及网络]第8章输入输出.doc

上传人:sccc 文档编号:4561414 上传时间:2023-04-27 格式:DOC 页数:35 大小:208.50KB
返回 下载 相关 举报
[计算机硬件及网络]第8章输入输出.doc_第1页
第1页 / 共35页
[计算机硬件及网络]第8章输入输出.doc_第2页
第2页 / 共35页
[计算机硬件及网络]第8章输入输出.doc_第3页
第3页 / 共35页
[计算机硬件及网络]第8章输入输出.doc_第4页
第4页 / 共35页
[计算机硬件及网络]第8章输入输出.doc_第5页
第5页 / 共35页
点击查看更多>>
资源描述

《[计算机硬件及网络]第8章输入输出.doc》由会员分享,可在线阅读,更多相关《[计算机硬件及网络]第8章输入输出.doc(35页珍藏版)》请在三一办公上搜索。

1、第八章 输入输出Java所有的I/O机制都是基于数据流的,这些数据流表示了字符或者字节数据的流动序列。Java的I/O流提供了读写数据的标准方法。任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法。 Java.io是大多数面向数据流的输入/输出类的主要软件包。这个软件包包含了两个抽象类,InputStream和OutputStream。所有其它面象数据流的输入/输出类都要扩展这两个基类。 java.io软件包提供了一些类和接口,它们在由InputStream和OuputStream类提供的读写操作的顶端定义了一些有用的抽象。例如,ObjectInputStream类提供了把

2、输入/输出流中的数据当成对象来读取的方法,而ObjectOutputStream类提供了把Java对象写入数据流中的方法。数据从一个输入源获得。程序的结果被送到输出目的地。Java中,这些源和目的地被广泛的定义。例如一个网络连接器,内存缓冲区或磁盘文件可以被Java输入/输出类熟练的操作。尽管从物理上很难说明,这些外设都由相同的抽象体流(stream)来处理。流(stream)是一个生产或消费信息的逻辑实体。流通过Java输入/输出系统与物理设备相连。尽管与之相连的实际的物理设备各不相同,所有的流都以同样的方式运转。8.1 Java输入/输出类和接口java.io定义的输入/输出类列于下:1B

3、ufferedInputStream 2. FileWriter 3. PipedInputStream4BufferedOutputStream 5. FilterInputStream 6. PipedOutputStream7BufferedReader 8. FilterOutputStream 9. PipedReader等。ObjectInputStream.GetField 和ObjectOutputStream.PutField 是Java 2新添的内部类。java.io包还包含两个不受java 2欢迎的类,这两个类没有在上表中列出:LineNumber InputStream

4、和StringBufferInputStream。新代码不应该使用两个类。下面是由java.io定义的接口:DataInput FilenameFilter ObjectOutputDataOutput ObjectInput ObjectStreamConstantsExternalizable ObjectInputValidation SerializableFileFilterFileFilter接口是Java 2新增的。java.io包中有很多类和接口。包括字节和字符流,对象序列化(对象的存储和释放)。本章讲述几个最常用的I/O成员,从最独特的File开始。8.2 File(文件类)

5、尽管java.io定义的大多数类是实行流式操作的,File类不是。它直接处理文件和文件系统。也就是说,File类没有指定信息怎样从文件读取或向文件存储;它描述了文件本身的属性。File对象用来获取或处理与磁盘文件相关的信息,例如权限,时间,日期和目录路径。此外,File还浏览子目录层次结构。很多程序中文件是数据的根源和目标。尽管它们在小应用程序中因为安全原因而受到严格限制,文件仍是存储固定和共享信息的主要资源。Java中的目录当成File 对待,它具有附加的属性 一个可以被 list( )方法检测的文件名列表。下面的构造函数可以用来生成File 对象:File(String directory

6、Path)File(String directoryPath, String filename)File(File dirObj, String filename)这里,directoryPath是文件的路径名,filename 是文件名,dirObj 一个指定目录的File 对象。下面的例子创建了三个文件:f1,f2,和f3。第一个File对象是由仅有一个目录路径参数的构造函数生成的。第二个对象有两个参数路径和文件名。第三个File对象的参数包括指向f1文件的路径及文件名。f3和f2指向相同的文件。File f1 = new File(/);File f2 = new File(/,auto

7、exec.bat);File f3 = new File(f1,autoexec.bat);注意:Java 能正确处理UNIX和Windows/DOS约定路径分隔符。如果在Windows版本的Java下用斜线(/),路径处理依然正确。如果用Windows/DOS使用反斜线()的约定,需要在字符串内使用它的转义序列()。Java约定是用UNIX和URL风格的斜线来作路径分隔符。File 定义了很多获取File对象标准属性的方法。例如getName( )返回文件名,getParent( )返回父目录名,exists( )在文件存在的情况下返回true,反之返回false。然而File类是不对称的。

8、说它不对称,意思是虽然存在允许验证一个简单文件对象属性的很多方法,但是没有相应的函数来改变这些属性。下面的例子说明了几个File方法:例8.1 : / Demonstrate File.import java.io.File;class FileDemo static void p(String s) System.out.println(s);public static void main(String args) File f1 = new File(/java/COPYRIGHT);p(File Name: + f1.getName();p(Path: + f1.getPath();p(

9、Abs Path: + f1.getAbsolutePath();p(Parent: + f1.getParent();p(f1.exists() ? exists : does not exist);p(f1.canWrite() ? is writeable : is not writeable);p(f1.canRead() ? is readable : is not readable);p(is + (f1.isDirectory() ? : not + a directory);p(f1.isFile() ? is normal file : might be a named pi

10、pe);p(f1.isAbsolute() ? is absolute : is not absolute);p(File last modified: + f1.lastModified();p(File size: + f1.length() + Bytes);运行该程序,将看到下面的结果:File Name: COPYRIGHTPath: /java/COPYRIGHTAbs Path: /java/COPYRIGHTParent: /javaexistsis writeableis readableis not a directoryis normal fileis absoluteF

11、ile last modified: 812465204000File size: 695 Bytes大多数File方法是自说明的,但isFile( )和isAbsolute( )不是。isFile( )在被文件调用时返回true,在被目录调用时返回false。并且,isFile( )被一些专用文件调用时返回false,例如设备驱动程序和命名管道,所以该方法可用来判定文件是否作为文件执行。isAbsolute( )方法在文件拥有绝对路径时返回true,若是相对路径则返回false。File 还包括两个有用的实用工具方法。第一个是renameTo( ),显示如下:boolean renameTo

12、(File newName)这里,由newName指定的文件名变成了所调用的File 对象的新的名称。如果更名成功则返回ture,文件不能被重命名(例如,试图重命名文件以使它从一个目录转到另一个目录,或者使用了一个已经存在的文件名),则返回false。第二个实用工具方法是delete( ),该方法删除由被调用的File对象的路径指定的磁盘文件。它的形式如下:boolean delete( )同样可以在目录为空时用delete( )删除目录。如果删除了文件,delete( )返回true,如果文件不能被删除则返回false。Java 2 为File 类增添了一些新的方法,在某些场合这些新增方法很

13、有用。一些最有趣的方法显示如下:方法 描述void deleteOnExit( ) 在java虚拟机终止时删除与调用对象相关的文件boolean isHidden( ) 如果调用的文件是隐藏的,返回true;否则返回 false。boolean setLastModified(long millisec) 设置由millisec指定的调用文件的时间标志,Millisec是从1970年1月1号开始的标准时间(UTC)的毫秒数boolean setReadOnly( ) 设置调用文件为只读并且,因为File 类现在支持Comparable 接口,compareTo( )方法也被支持。8.2.1 目

14、录目录是一个包含其他文件和路径列表的File 类。当创建一个File 对象且它是目录时,isDirectory( ) 方法返回ture。这种情况下,可以调用该对象的list( )方法来提取该目录内部其他文件和目录的列表。该方法有两种形式。第一种形式如下:String list( )文件列表在一个String 对象数组中返回。下面显示的程序说明怎样用list( )来检查一个目录的内容:例8.2: import java.io.File;class DirList public static void main(String args) String dirname = /java;File f1

15、 = new File(dirname);if (f1.isDirectory() System.out.println(Directory of + dirname);String s = f1.list();for (int i=0; i s.length; i+) File f = new File(dirname + / + si);if (f.isDirectory() System.out.println(si + is a directory); else System.out.println(si + is a file); else System.out.println(di

16、rname + is not a directory);下面是程序的样本输出(当然,目录下的内容不同,输出也不同):Directory of /javabin is a directorylib is a directorydemo is a directoryCOPYRIGHT is a fileREADME is a fileindex.html is a fileinclude is a directorysrc.zip is a file.hotjava is a directorysrc is a directory8.2.2 使用FilenameFilter人们总是希望能够限制由l

17、ist( )方法返回的文件数目,使它仅返回那些与一定的文件名方式或者过滤(filter)相匹配的文件。为达到这样的目的,必须使用list( )的第二种形式:String list(FilenameFilter FFObj)该形式中,FFObj是一个实现FilenameFilter接口的类的对象。FilenameFilter仅定义了一个方法,accept( )。该方法被列表中的每个文件调用一次。它的通常形式如下:boolean accept(File directory, String filename)当被directory 指定的目录中的文件(也就是说,那些与filename 参数匹配的文件

18、)包含在列表中时,accept( )方法返回true ,当这些文件没有包括在列表中时,accept( )返回false。下面显示的OnlyExt 类实现FilenameFilter接口,它被用来修饰前面的程序,限制由 list( )返回的文件名的可见度,把对象被创建时以指定扩展名结束的文件归档。例8.3 : import java.io.*;public class OnlyExt implements FilenameFilter String ext;public OnlyExt(String ext) this.ext = . + ext;public boolean accept(Fi

19、le dir, String name) return name.endsWith(ext); 修改过的目录列表程序显示如下。现在它只显示以.html 为扩展名的文件。例8.4 : / Directory of .HTML files.import java.io.*;class DirListOnly public static void main(String args) String dirname = /java;File f1 = new File(dirname);FilenameFilter only = new OnlyExt(html);String s = f1.list(

20、only);for (int i=0; i s.length; i+) System.out.println(si); 8.2.3 listFiles()方法Java 2增加了list( )方法的一个变化形式,名为listFiles( ),该方法很有用。listFiles( )形式如下:File listFiles( )File listFiles(FilenameFilter FFObj)File listFiles(FileFilter FObj)上述三种形式以File对象矩阵的形式返回文件列表,而不是用字符串形式返回。第一种形式返回所有的文件,第二种形式返回满足指定FilenameFil

21、ter接口的文件。除了返回一个File 对象数组,这两个listFiles( )方法就像list( )方法一样工作。第三种listFiles( )形式返回满足指定FileFilter的路径名的文件。FileFilter只定义了一个accept( )方法,该方法被列表中的每个文件调用一次。它的通常形式如下:boolean accept(File path)如果文件被包括在列表中(即与path参数匹配的文件),accept( )方法返回true,如果不被包括,则返回false。8.2.4 创建目录另外两个有用的File类的方法是mkdir( )和mkdirs( )。mkdir( )方法创建了一个目

22、录,创建成功返回true,创建失败返回false。创建失败是指File对象指定的目录已经存在,或者是因为整个路径不存在而不能创建目录。创建路径不存在的目录,用mkdirs( )的方法。它创建目录以及该目录所有的父目录。8.3 流 类Java 的流式输入/输出建立在四个抽象类的基础上:InputStream, OutputStream, Reader和Writer。它们用来创建具体流式子类。尽管程序通过具体子类执行输入/输出操作,顶层的类定义了所有流类的基础通用功能。InputStream 和OutputStream 设计成字节流类。Reader 和Writer 为字符流设计。字节流类和字符流类

23、形成分离的层次结构。一般说来,处理字符或字符串时应使用字符流类,处理字节或二进制对象时应用字节流类。下面分别讲述字节流和字符流类。8.4 字 节 流字节流类为处理字节式输入/输出提供了丰富的环境。一个字节流可以和其他任何类型的对象并用,包括二进制数据。这样的多功能性使得字节流对很多类型的程序都很重要。因为字节流类以InputStream 和OutputStream为顶层,我们就从讨论这两个类开始。8.4.1 InputStream(输入流)InputStream 是一个定义了Java流式字节输入模式的抽象类。该类的所有方法在出错条件下引发一个IOException 异常。以下是方法描述:int

24、 available( ) 返回当前可读的输入字节数。void close( ) 关闭输入源。关闭之后的读取会产生IOException异常。void mark(int numBytes) 在输入流的当前点放置一个标记。该流在读取numBytes个字节前都保持有效。boolean markSupported( ) 如果调用的流支持mark( )/reset( )就返回true。int read( ) 如果下一个字节可读则返回一个整型,遇到文件尾时返回-1。int read(byte buffer ) 试图读取buffer.length个字节到buffer中,并返回实际成功读取的字节数。遇到文件

25、尾时返回-1。int read(byte buffer , int offset,int numBytes)试图读取buffer中从bufferoffset开始的numBytes个字节,返回实际读取的字节数。遇到文件尾时返回-1。void reset( ) 重新设置输入指针到先前设置的标志处。long skip(long numBytes) 忽略numBytes个输入字节,返回实际忽略的字节数。8.4.2 OutputStream(输出流)OutputStream是定义了流式字节输出模式的抽象类。该类的所有方法返回一个void 值并且在出错情况下引发一个IOException异常。以下是方法描

26、述:void close( ) 关闭输出流。关闭后的写操作会产生IOException异常void flush( ) 定制输出状态以使每个缓冲器都被清除,也就是刷新输出缓冲区void write(int b) 向输出流写入单个字节。注意参数是一个整型数,它允许用户不必把参数转换成字节型就可以调用write()void write(byte buffer ) 向一个输出流写一个完整的字节数组void write(byte buffer , int offset,int numBytes)写数组buffer以bufferoffset为起点的numBytes个字节区域内的内容注意:多数I/O的方法由

27、InputStream 和OutputStream的子类实现,但mark( )和reset( )方法除外。注意下面讨论的每个子类中它们的使用和不用情况。 8.4.3 FileInputStream(文件输入流)FileInputStream 类创建一个能从文件读取字节的InputStream 类,它的两个常用的构造函数如下:FileInputStream(String filepath)FileInputStream(File fileObj)它们都能引发FileNotFoundException异常。这里,filepath 是文件的全称路径,fileObj是描述该文件的File对象。下面的例

28、子创建了两个使用同样磁盘文件且各含一个上述构造函数的FileInputStreams类:FileInputStream f0 = new FileInputStream(/autoexec.bat)File f = new File(/autoexec.bat);FileInputStream f1 = new FileInputStream(f);尽管第一个构造函数可能更常用到,第二个构造函数允许在把文件赋给输入流之前用File方法更进一步检查文件。当一个FileInputStream被创建时,它可以被公开读取。FileInputStream重载了抽象类InputStream的六个方法,ma

29、rk( )和reset( )方法不被重载,任何关于使用FileInputStream的reset()尝试都会生成IOException异常。下面的例题说明了怎样读取单个字节、字节数组以及字节数组的子界。它同样阐述了怎样运用available( )判定剩余的字节个数及怎样用skip( )方法跳过不必要的字节。该程序读取它自己的源文件,该源文件必定在当前目录中。例8.5 : / Demonstrate FileInputStream.import java.io.*;class FileInputStreamDemo public static void main(String args) thr

30、ows Exception int size;InputStream f =new FileInputStream(FileInputStreamDemo.java);System.out.println(Total Available Bytes: +(size = f.available();int n = size/40;System.out.println(First + n + bytes of the file one read() at a time);for (int i=0; i n; i+) System.out.print(char) f.read();System.ou

31、t.println(nStill Available: + f.available();System.out.println(Reading the next + n + with one read(b);byte b = new byten;if (f.read(b) != n) System.err.println(couldnt read + n + bytes.);System.out.println(new String(b, 0, n);System.out.println(nStill Available: + (size = f.available();System.out.p

32、rintln(Skipping half of remaining bytes with skip();f.skip(size/2);System.out.println(Still Available: + f.available();System.out.println(Reading + n/2 + into the end of array);if (f.read(b, n/2, n/2) != n/2) System.err.println(couldnt read + n/2 + bytes.);System.out.println(new String(b, 0, b.lengt

33、h);System.out.println(nStill Available: + f.available();f.close();下面是该程序的输出:Total Available Bytes: 1433First 35 bytes of the file one read() at a time/ Demonstrate FileInputStream.imStill Available: 1398Reading the next 35 with one read(b)port java.io.*;class FileInputSStill Available: 1363Skipping

34、half of remaining bytes with skip()Still Available: 682Reading 9 into the end of arrayport java.io.*;read(b) != n) SStill Available: 665 这个有些刻意创作的例子说明了怎样读取数据的三种方法,怎样跳过输入以及怎样检查流中可以获得数据的数目。8.4.4 FileOutputStream(文件输出流)FileOutputStream 创建了一个可以向文件写入字节的类OutputStream,它常用的构造函数如下:FileOutputStream(String fil

35、ePath)FileOutputStream(File fileObj)FileOutputStream(String filePath, boolean append)它们可以引发IOException或SecurityException异常。这里filePath是文件的全称路径,fileObj是描述该文件的File对象。如果append为true,文件以设置搜索路径模式打开。FileOutputStream的创建不依赖于文件是否存在。在创建对象时FileOutputStream在打开输出文件之前创建它。这种情况下用户试图打开一个只读文件,会引发一个IOException异常。下面的例子创建

36、一个样本字节缓冲器。先生成一个String对象,接着用getBytes( )方法提取字节数组对等体。然后创建了三个文件。第一个file1.txt将包括样本中的各个字节。第二个文件是file2.txt,它包括所有字节。第三个也是最后一个文件file3.txt,仅包含最后的四分之一。不像FileInputStream类的方法,所有FileOutputStream类的方法都返回一个void类型值。在出错情况下,这些方法将引发IOException异常。例8.6 : / Demonstrate FileOutputStream.import java.io.*;class FileOutputStre

37、amDemo public static void main(String args) throws Exception String source = Now is the time for all good menn+ to come to the aid of their countryn+ and pay their due taxes.;byte buf = source.getBytes();OutputStream f0 = new FileOutputStream(file1.txt);for (int i=0; i buf.length; i += 2) f0.write(b

38、ufi);f0.close();OutputStream f1 = new FileOutputStream(file2.txt);f1.write(buf);f1.close();OutputStream f2 = new FileOutputStream(file3.txt);f2.write(buf,buf.length-buf.length/4,buf.length/4);f2.close();下面是运行该程序之后,每个文件的内容,首先是file1.txt:Nwi h iefralgo et oet h i ftercuty n a hi u ae.接着,是file2.txt:Now

39、is the time for all good mento come to the aid of their countryand pay their due taxes.最后,file3.txtnd pay their due taxes.8.4.5 ByteArrayInputStream(字节数组输入流)ByteArrayInputStream是把字节数组当成源的输入流。该类有两个构造函数,每个构造函数需要一个字节数组提供数据源:ByteArrayInputStream(byte array )ByteArrayInputStream(byte array , int start, i

40、nt numBytes)这里,array是输入源。第二个构造函数创建了一个InputStream类,该类从字节数组的子集生成,以start指定索引的字符为起点,长度由numBytes决定。下面的例子创建了两个ByteArrayInputStream,用字母表的字节表示初始化它们:例8.7 : / Demonstrate ByteArrayInputStream.import java.io.*;class ByteArrayInputStreamDemo public static void main(String args) throws IOException String tmp = a

41、bcdefghijklmnopqrstuvwxyz;byte b = tmp.getBytes();ByteArrayInputStream input1 = new ByteArrayInputStream(b);ByteArrayInputStream input2 = new ByteArrayInputStream(b, 0,3);input1对象包含整个字母表中小写字母,input2仅包含开始的三个字母。ByteArrayInputStream实现mark( )和reset( )方法。然而,如果 mark( )不被调用,reset( )在流的开始设置流指针该指针是传递给构造函数的字节

42、数组的首地址。下面的例子说明了怎样用reset( )方法两次读取同样的输入。这种情况下,我们读取数据,然后分别用小写和大写字母打印abc。例8.8 : import java.io.*;class ByteArrayInputStreamReset public static void main(String args) throws IOException String tmp = abc;byte b = tmp.getBytes();ByteArrayInputStream in = new ByteArrayInputStream(b);for (int i=0; i2; i+) in

43、t c;while (c = in.read() != -1) if (i = 0) System.out.print(char) c); else System.out.print(Character.toUpperCase(char) c);System.out.println();in.reset();该例先从流中读取每个字符,然后以小写字母形式打印。然后重新设置流并从头读起,这次在打印之前先将字母转换成大写字母。下面是输出:abcABC 8.4.6 ByteArrayOutputStream(字节数组输出流)ByteArrayOutputStream是一个把字节数组当作输出流的实现。B

44、yteArrayOutputStream有两个构造函数,如下:ByteArrayOutputStream( )ByteArrayOutputStream(int numBytes)在第一种形式里,一个32位字节的缓冲器被生成。第二个构造函数生成一个跟指定numBytes相同位数的缓冲器。缓冲器保存在ByteArrayOutputStream的受保护的buf 成员里。缓冲器的大小在需要的情况下会自动增加。缓冲器保存的字节数是由ByteArrayOutputStream的受保护的count域保存的。下面的例子说明了ByteArrayOutputStream:例8.9 : / Demonstrate

45、 ByteArrayOutputStream.import java.io.*;class ByteArrayOutputStreamDemo public static void main(String args) throws IOException ByteArrayOutputStream f = new ByteArrayOutputStream();String s = This should end up in the array;byte buf = s.getBytes();f.write(buf);System.out.println(Buffer as a string)

46、;System.out.println(f.toString();System.out.println(Into array);byte b = f.toByteArray();for (int i=0; iSystem.out.print(char) bi);System.out.println(nTo an OutputStream();OutputStream f2 = new FileOutputStream(test.txt);f.writeTo(f2);f2.close();System.out.println(Doing a reset);f.reset();for (int i=0; i3; i+)f.write(X);System.out.println(f.toString();运行程序后

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 教育教学 > 成人教育


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号