《java第6章_io流免费.ppt》由会员分享,可在线阅读,更多相关《java第6章_io流免费.ppt(99页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第6章 I/O:读和写课前思考1.如何读取硬盘上的某个文件内容?2.如何知道文件系统中有哪些目录和子目录?3.如何往硬盘上写文件?4.如何接收键盘输入?教学目标与外部设备和其它计算机进行交流的输入输出操作,尤其是对磁盘的文件操作,是计算机程序重要的功能,任何计算机语言都必须对输入输出提供支持。Java也不例外,它的输入输出类库中包含了丰富的系统工具,这些类被放在java.io包中。在该类库中,除了定义文件输入输出操作外,还定义了许多用来和其他外设进行信息交换的类。本章将详细介绍I/O类库中的基本内容,主要侧重于文件的输入输出管理和流的基本概念。流v在计算机中,“流”的概念是1984年由C语言第
2、一次引入的。“流”可以看作是一个流动的数据缓冲区,数据从数据源流向数据目的地。I/O与流vI/OI/O是程序设计中的重要问题,大部分的应用是程序设计中的重要问题,大部分的应用程序都需要程序都需要I/OI/O操作,比如从键盘获得用户输操作,比如从键盘获得用户输入、在屏幕输出运行结果、对磁盘文件进行入、在屏幕输出运行结果、对磁盘文件进行读写等等。应用程序只有通过读写等等。应用程序只有通过I/OI/O操作才能实操作才能实现与用户的交互及数据的处理及存储现与用户的交互及数据的处理及存储.v在在JavaJava语言中,将不同类型的语言中,将不同类型的I/OI/O抽象为流。抽象为流。所谓所谓“流(流(st
3、reamstream)”,可以看作是数据在,可以看作是数据在文件或程序之间的传递文件或程序之间的传递 输入流和输出流 v一般来说,流有两种基本形式:输入流和输一般来说,流有两种基本形式:输入流和输出流,根据程序是作为数据流的目的端还是出流,根据程序是作为数据流的目的端还是源端来划分。程序首先要打开一个流,才能源端来划分。程序首先要打开一个流,才能与数据文件进行通信。与数据文件进行通信。v通过输入流,程序可以从数据文件读取数据,通过输入流,程序可以从数据文件读取数据,但不可向输入流中写入数据;反之,通过输但不可向输入流中写入数据;反之,通过输出流,程序可以向数据文件中写入数据。程出流,程序可以向
4、数据文件中写入数据。程序与其他设备间的序与其他设备间的I/OI/O也可以使用流,这时可也可以使用流,这时可将设备看作是一个数据文件。将设备看作是一个数据文件。Java I/O流类的组织模式 java.iov在在JavaJava开发环境中,主要是由包开发环境中,主要是由包java.iojava.io中提供的一系列的中提供的一系列的类和接口来实现输入类和接口来实现输入/输出处理。而标准输入输出处理。而标准输入/输出处理则是输出处理则是由包由包java.langjava.lang中提供的类来处理的,这些类又都是从包中提供的类来处理的,这些类又都是从包java.iojava.io中的类继承而来的。中的
5、类继承而来的。vI/OI/O类提供了低层次和高层次的界面。每一种介质都有一对类提供了低层次和高层次的界面。每一种介质都有一对与之相关联的输入输出类,它们提供低层次的面向数据序列与之相关联的输入输出类,它们提供低层次的面向数据序列(字符、字节)的界面(字符、字节)的界面。与介质相关的各个类都分别是输入与介质相关的各个类都分别是输入输出抽象流类的子类,它们通常具有与介质相关的构造器及输出抽象流类的子类,它们通常具有与介质相关的构造器及方法。方法。vI/OI/O抽象类为所有与介质相关的具体输入输出类提供了一个抽象类为所有与介质相关的具体输入输出类提供了一个统一的界面。反过来各个具体的与介质相关的输入
6、输出类也统一的界面。反过来各个具体的与介质相关的输入输出类也扩展了抽象类,通过它们可以实现在具体介质上的输入输出扩展了抽象类,通过它们可以实现在具体介质上的输入输出操作操作 I/O操作的一般步骤 v构造一个与介质相关的构造一个与介质相关的I/OI/O对象,以提供一种对象,以提供一种低层次的方法将数据输入或输出到相应的介低层次的方法将数据输入或输出到相应的介质;质;v将与介质相关的对象强制类型转换为它的父将与介质相关的对象强制类型转换为它的父类(即抽象类(即抽象I/OI/O类),并利用该对象构造一个类),并利用该对象构造一个流对象。这样便建立起了流类对象与介质相流对象。这样便建立起了流类对象与介
7、质相关对象的关联;关对象的关联;v这时就可利用流对象的这时就可利用流对象的I/OI/O方法进行相应介质方法进行相应介质上的数据读写。上的数据读写。字节流与字符流v从流中传输的数据单位分为两类:v字节流从InputStream和OutputStream派生出来的一系列类,以字节(byte)为基本处理单位。v字符流从Reader和Writer派生出的一系列类,以16位的Unicode码表示的字符为基本处理单位。字节流InputStream类vInputStreamInputStream类定义了一套所有字节输入流所需类定义了一套所有字节输入流所需的方法的方法 方法方法描述描述read()read()
8、将数据读入流中将数据读入流中skip()skip()跳过流中的若干字节跳过流中的若干字节available()available()返回当前流中的可用字节返回当前流中的可用字节mark()mark()在流中标记一个位置在流中标记一个位置reset()reset()返回到流中的标记位置返回到流中的标记位置markSupportedmarkSupported()()返回一个返回一个booleanboolean值,描述流是否支持标记和复位值,描述流是否支持标记和复位close()close()关闭流关闭流OutputStream类vOutputStreamOutputStream类定义了一套所有字节
9、输出流类定义了一套所有字节输出流所需的方法。所需的方法。方法方法描述描述write()写数据到流写数据到流flush()强制将被缓冲的内容写到输出强制将被缓冲的内容写到输出close()关闭流关闭流字符流类Reader与Writer类vReader类的相关方法:类的相关方法:void close()void mark(int readAheadLimit)boolean markSupported()int read()int read(char cbuf)int read(char cbuf,int off,int len)boolean ready()void reset()long sk
10、ip(long n)vWriter类的相关方法:类的相关方法:void close()void flush()void write(char cbuf)void write(char cbuf,int off,int len)void write(int c)void write(String str)void write(String str,int off,int len)各种流的作用概述I/O类型类型流流作用作用内存CharArrayReaderCharArrayWriterByteArrayInputStreamByteArrayOutputStream用来从内存读取数据或向内存写入数
11、据StringReaderStringWriterStringBufferInputStream从内存里的某个String或StringBuffer读字符或字节管道PipedReaderPipedWriterPipedInputStreamPipedOutputStream实现一个输入、输出管道。管道可用于一个线程的输出连接到另一个线程的输入各种流的作用概述文件文件FileReaderFileWriterFileInputStreamFileOutputStream用于对本机文件系统上的一个用于对本机文件系统上的一个件行读写件行读写联结联结N/ASequenceInputStream将多个输入
12、流联结成为一个输将多个输入流联结成为一个输入流入流对象串行化对象串行化N/AObjectInputStreamObjectOutputStream将对象串行化将对象串行化数据转换数据转换N/ADataInputStreamDataOutputStream以一种与机器无关的格式读写以一种与机器无关的格式读写原始数据类型原始数据类型各种流的作用概述计数计数LineNumberReaderLineNumberInputStream在读取时记录行数在读取时记录行数预览预览PushbackReaderPushbackInputStream带有带有“回推回推(pushback)”缓冲区的输入流缓冲区的输入
13、流打印打印PrintWriterPrintStream包含便捷的打印方法的流。包含便捷的打印方法的流。各种流的作用概述缓冲缓冲BufferedReaderBufferedWriterBufferedInputStreamBufferedOutputStream缓冲流,用于在读写时进行数据缓冲缓冲流,用于在读写时进行数据缓冲过滤过滤FilterReaderFilterWriterFilterInputStreamFilterOutputStream过滤流的抽象类接口。数据读写时对过滤流的抽象类接口。数据读写时对数据进行过滤数据进行过滤在字节和在字节和字符之间字符之间转换转换InputStream
14、ReaderOutputStreamWriter字节流和字符类间的转换桥梁字节流和字符类间的转换桥梁文件流v要对本机文件系统上的文件进行读写,需要要对本机文件系统上的文件进行读写,需要使用文件流。使用文件流。JavaJava的文件流类包括字符流的的文件流类包括字符流的FileReaderFileReader、FileWriterFileWriter和字节流的和字节流的FileInputStreamFileInputStream、FileOutputStreamFileOutputStream。Java中文件的操作v 而要进行文件流操作,首先必须清楚java中关于文件的基本操作,下面我们进行详细
15、介绍。文件与目录的描述类File File类并不用来进行文件的读/写操作,它用来描述文件对象的属性,既可以表示文件,也可以表示目录。使用它提供的方法,我们可以得到所指对象的描述信息,包括名称、存在否、读/写权限、路径等等。需要注意的是,当我们在Windows环境使用路径时,其分隔符不能是单一的“”符号,因为与C/C+相同,符号“”已经被转意了。例如:vc:jbuilder3javabinv路径是非法的,系统不会识别,正确的应该为vc:jbilder3javabin 或者直接使用反斜杠/来作为路径分隔符。如c:/jbilder3/java/bin文件描述v类File提供了一种与机器无关的方式来描
16、述一个文件对象的属性。v文件的生成public File(String path);public File(String path,String name);public File(File dir,String name);文件描述v文件名的处理String getName();/*得得到到一一个个文文件件的的名名称称(不不包包括路径)括路径)*/String getPath();/得到一个文件的路径名得到一个文件的路径名String getAbsolutePath();/*得得到到一一个个文文件件的的绝绝对路径名对路径名*/String getParent();/*得到一个文件的上一级目得
17、到一个文件的上一级目录名录名*/String renameTo(File newName);/*将将当当前前文文件件名名更名为给定文件的完整路径更名为给定文件的完整路径*/文件描述v文件属性测试boolean exists();/*测测试试当当前前File对对象象所所指指示示的的文件是否存在文件是否存在*/boolean canWrite();/测试当前文件是否可写测试当前文件是否可写boolean canRead();/测试当前文件是否可读测试当前文件是否可读boolean isFile();/*测试当前文件是否是文件测试当前文件是否是文件(不是目录)(不是目录)*/boolean isDi
18、rectory();/*测测试试当当前前文文件件是是否否是是目录目录*/文件描述v普通文件信息和工具long lastModified();/*得到文件最近一次修改的得到文件最近一次修改的时间时间*/long length();/得到文件的长度,以字节为单位得到文件的长度,以字节为单位boolean delete();/删除当前文件删除当前文件v目录操作boolean mkdir();/*根据当前对象生成一个由该对根据当前对象生成一个由该对象指定的路径象指定的路径*/String list();/列出当前目录下的文件列出当前目录下的文件File类的方法及变量方法及变量名功能描述public F
19、ile(File dir,String name)由指定的目录、名字创建该对象public File(String path,String name)由指定的路径、名字创建该对象public File(String path)由指定路径创建该对象public staticfinal String pathSeparator返回系统的路径分隔符public boolean canRead()如果文件可读为真public boolean canWrite()如果文件可写为真public boolean delete()删除文件public boolean equals(Object obj)文件比
20、较,如是同一个文件则为真public boolean exists()指定的文件存在返回真public String getAbsolutePath()得到文件的绝对路径public String getName()得到文件名public String getParent()得到父目录的名字public String getPath()返回路径public int hashCode()返回一个哈希码public nativeboolean isAbsolute()如果是绝对路径返回真public boolean isDirectory()如果是目录则返回真public boolean isFi
21、le()如果是文件则返回真public long lastModified()返回最近一次修改时间public long length()返回文件长度public String list(FilenameFilter filter)返回指定格式的目录中的文件名public String list()返回当前目录中的所有文件名public boolean mkdir()创建目录,成功返回真public boolean mkdirs()创建路径中所有目录,成功则返回真public static final char pathSeparatorChar返回路径分隔符public boolean re
22、nameTo(Filedest)文件更名,成功返回真public static final char separatorChar返回文件分隔符public String toString()返回对象的字符串表示 下面我们给出几个File类的应用实例。通过例题的使用,希望对File类有更清楚的认识。例v import java.io.*;v public class MyClass1 v public static void main(String args)v Filef=new File(c:jbuilder3myprojectsuntitled5MyClass1.java);v if(!f
23、.exists()v System.out.println(File MyClass1.java doesnt exist!);v else v System.out.println(This file can read +f.canRead();v System.out.println(last modified+f.lastModified();v System.out.println(Parent is+f.getParent();v System.out.println(File length is+f.length();v v public MyClass1()v 图 7.3例 im
24、port java.io.*;class FileTestpublic static void main(String args)System.out.println(path separator+File.pathSeparator);System.out.println(path separator char+File.pathSeparatorChar);System.out.println(separator+File.separator);System.out.println(separator char+File.separatorChar);File f=new File(/do
25、ng1/test1.class);System.out.println();System.out.println(f);System.out.println(exist?+f.exists();System.out.println(name+f.getName();System.out.println(path+f.getPath();System.out.println(absolute path+f.getAbsolutePath();System.out.println(parent+f.getParent();System.out.println(is a file?+f.isFile
26、();System.out.println(is a directory?+f.isDirectory();System.out.println(length+f.length();System.out.println(can read+f.canRead();System.out.println(can write+f.canWrite();System.out.println(last modified+f.lastModified();File newF=new File(newFile);System.out.println(.Rename+f+.);f.renameTo(newF);
27、System.out.println(name+newF.getName();System.out.println(f+exist?+f.exists();System.out.println(.delete+newF+.);newF.delete();System.out.println(newF+exist?+newF.exists();运行结果path separator :path separator char:separator/separator char/dong1/test1.classexist?truename test1.classpath/dong1/test1.cla
28、ssabsolute path/dong1/test1.classparent/dong1运行结果is a file?trueis a directory?falselength 514can read truecan write truelast modified 907117020000.Rename/dong1/test1.classname newFile/dong1/test1.class exist?false.delete newFile.newFile exist?false文件夹处理vlist方法用于列出一个目录中所有的文件或与某个模式相匹配的文件。v列出目录中与某种模式相匹
29、配的文件:public String list(FilenameFilter filter);在接口 FilenameFilter中定义的方法只有:boolean accept(File dir,String name);例:import java.io.*;public class FileFilterTestpublic static void main(String args)File dir=new File(“/dongl”);Filter filter=new Filter(“htm”);System.out.println(“list html files in director
30、y ”+dir);String files=dir.list(filter);for(int i=0;ifiles.length;i+)File f=new File(filesi);if(f.isFile()System.out.println(“file”+f);elseSystem.out.println(“sub directory”+f);class Filter implements FilenameFilterString extent;Filter(String extent)this.extent=extent;public boolean accept(File dir,S
31、tring name)return name.endsWith(“.”+extent);运行结果list html files in directoty/donglfile cert_test.htmfile cert_sample.htmfile cert_obj.htmv例vimport java.io.*;vpublic class MyClass2 v public static void main(String args)v File f1=new File(c:jbuilder3myprojects);v if(!f1.isDirectory()v System.out.print
32、ln(Error:+f1+isnt a directory!);v else String dirList=f1.list();v for(int i=0;idirList.length;i+)System.out.println(dirListi);v v public MyClass2()v v在该例中,我们并没有在调用File类的list方法中传递参数,这样,处在目录c:jbuilder3myprojects下的所有文件及目录将均被输出,结果如图7.4所示。图 7.4 v1Byte流(字节流)文件的读取v 该类的结构如图7.1所示,我们主要用其中的FileOutputStream和Fil
33、eInputStream类,它们的父类为InputStream和OutputStream。主要的方法有:v InputStreamv int read()v int read(byte buf)v int read(byte buf,int offset,int length)v close()利用流进行文件I/O处理v OutputStreamvint write(int c)vint write(byte buf)vint write(byte buf,int offset,int length)vclose()v下面给出一个应用实例7.4。图 7.5v 例7.4v import java
34、.io.*;v public class FileCopy v public static void main(String args)throws IOExceptionv FileInputStream f1;v FileOutputStream f2;v f1=new FileInputStream(FileCopy.java);v f2=new FileOutputStream(acopy_of_java_file);v int temp;v while(temp=f1.read()!=-1)v f2.write(temp);v f1.close();f1.close();v publ
35、ic FileCopy()v v 在该例中,我们利用字节流将本程序拷贝至另一个文件acopy_of_java_file中,如果指定的文件不存在,则创建一个新文件,否则原文件的内容会被新写入的内容覆盖。当程序运行后,将生成一个与原程序相同的副本。v 2Character流(字符流)文件的读取v 该类如图7.2所示,输入/输出类的父类为Reader、Writer,其基本的方法有:v Readerv int read()v int read(char buf)v int read(char buf,int offset,int length)v close()v Writerv int write(
36、int c)v int write(char buf)v int write(char buf,int offset,int length)v close()v 读者可与字节流进行比较,注意二者方法的区别。下面我们用字符流来改写例7.4:v 例7.5v import java.io.*;v public class FileCopy v public static void main(String args)throws IOExceptionv FileReader f1;v FileWriter f2;v f1=new FileReader(FileCopy.java);v f2=new
37、FileWriter(acopy_of_java_file);vint temp;v while(temp=f1.read()!=-1)v f2.write(temp);v f1.close();f2.close();v public FileCopy()vv例7.6vimport java.io.*;vpublic class ReadFile v public static void main(String args)v throws IOException vFileReader fr=new FileReader(ReadFile.java);vBufferedReader br=ne
38、w BufferedReader(fr);vString line=br.readLine();vwhile(line!=null)v System.out.println(line);v line=br.readLine();v br.close();v v 本程序中,我们通过类BufferedReader对文件实现按行读取,达到一行一行输出的目的,结果如图7.6所示。图 7.6 v 3二进制数据流的文件读取v 如果要读取与机器无关的基本数据类型的数据,如整型或浮点型的二进制数,就要用到二进制数据文件流DataInputStream、DataOutputStream。实际使用中,类DataI
39、nputStream和DataOutputStream必须和一个输入类(InputStream)或输出类(OutputStream)联接起来,不能直接用文件名或文件对象(File)对其直接初始化,例如:v例7.7vimport java.io.*;vpublic class DatastreamDemo v public static void main(String args)v throws IOException v FileOutputStream f2=new FileOutputStream(data);v DataOutputStream dfo=new DataOutputSt
40、ream(f2);v dfo.writeBoolean(true);v dfo.writeInt(100);v dfo.writeFloat(200.2f);v f2.close();dfo.close();v FileInputStream f1=new FileInputStream(data);v DataInputStream dfi=new DataInputStream(f1);v boolean b=dfi.readBoolean();v int i=dfi.readInt();v float f=dfi.readFloat();v f1.close();dfi.close();
41、v System.out.println(The value is:);v System.out.println(+b);v System.out.println(+i);v System.out.println(+f);v public DatastreamDemo()v 该例中,我们首先利用类DataOutputStream生成一个二进制文件data,并对它写入三个不同类型的数据:布尔型、整型、浮点型。然后利用DataInputStream读入刚刚输入的数据并显示出来,结果如图7.7所示。可以看出,输出结果与我们的输入是一一对应的。图 7.7v 4随机访问文件的读取v 对于InputStr
42、eam/OutputStream、Reader/Writer类来说,它们都是顺序访问流,只能进行顺序读写。而所谓随机读写,是指读写完上一个字节后,不只能读写其后继的字节,还可以读写文件中任意的字节,就好象文件中有一个随意移动的指针一样。v Java语言提供了类RandomAccessFile来进行随机文件的读取。在生成一个RandomAccessFile对象时,不仅要说明文件对象或文件名,同时还需指明访问模式,即“只读方式”(r)或“读写方式”(rw),这类似于C/C+中的fopen()函数。随机文件处理v使用流的形式对文件进行读写必须顺序进行,也就使用流的形式对文件进行读写必须顺序进行,也就
43、是说这些文件流的数据必须按先后次序进行处理。是说这些文件流的数据必须按先后次序进行处理。在对某些顺序存储访问介质,例如磁带等进行访问在对某些顺序存储访问介质,例如磁带等进行访问时,这样的文件流方式非常有用时,这样的文件流方式非常有用 v随机文件存取提供了一种更灵活的文件读写方式,随机文件存取提供了一种更灵活的文件读写方式,它允许对文件的内容进行非顺序的访问。在这里,它允许对文件的内容进行非顺序的访问。在这里,“随机随机”是指所存取的数据不需要与以前存取过的是指所存取的数据不需要与以前存取过的历史数据有任何的关系。使用随即文件存取方式可历史数据有任何的关系。使用随即文件存取方式可以在打开一个文件
44、后同时进行读写操作,并且可以以在打开一个文件后同时进行读写操作,并且可以移动文件指针使其指向文件中的任何位置移动文件指针使其指向文件中的任何位置 随机存取文件的结构v在文件内部,文件被分成固定长度的数据块在文件内部,文件被分成固定长度的数据块(记录)。从概念上来说,文件可以看作是(记录)。从概念上来说,文件可以看作是一个记录数组。文件指针的移动是以记录为一个记录数组。文件指针的移动是以记录为单位的。单位的。RandomAccessFile类vRandomAccessFileRandomAccessFile类的构造函数使用了两个参数,类的构造函数使用了两个参数,第一个参数表示要操作的文件,可以使
45、用字符串类第一个参数表示要操作的文件,可以使用字符串类型的文件名也可以使用一个文件对象;第二个字符型的文件名也可以使用一个文件对象;第二个字符串类型的参数串类型的参数modemode表示了对文件的操作方式:表示了对文件的操作方式:modemode为为 ”r r”时表示可以从文件读取;时表示可以从文件读取;mode mode 为为 ”rwrw”时表示既可以从文件读取也可以向文件写入时表示既可以从文件读取也可以向文件写入 vRandomAccessFileRandomAccessFile类通过实现类通过实现DataInputDataInput和和DataOutPutDataOutPut的方法来实现
46、文件数据的读写,这些方的方法来实现文件数据的读写,这些方法允许使用二进制编码形式将基本的法允许使用二进制编码形式将基本的JavaJava类型写入类型写入或读出文件。在或读出文件。在RandomAccessFileRandomAccessFile类中还提供了一类中还提供了一些操作文件指针的方法,如通过些操作文件指针的方法,如通过seekseek方法可以将文方法可以将文件指针移动到其参数所制定的位置。件指针移动到其参数所制定的位置。v RandomAccessFile类的功能类似于DataOutputStream类和DataInputStream类的功能合并,即实现了在一个流中进行读、写两种功能。
47、其常用的方法如表7.2所示。表7.2 RandomAccessFile类的常用方法 方法名功能描述long getFilePointer()返回当前文件指针long length()返回文件长度boolean readBoolean()读入一个布尔值int readInt()读入一个整数string readLine()读入一行字符串void seek(long pos)文件指针移到指定位置int skipBytes(int n)文件指针向前移n个字节void write(byte b)把数组内容写入文件void writeBoolean(boolean v)写入一个布尔值void write
48、Int(int v)写入一个整数例程importjava.io.*;publicclassFileTestpublicstaticvoidmain(Stringargs)throwsIOExceptionRandomAccessFileraf=newRandomAccessFile(foo.txt,rw);try Writerout=newOutputStreamWriter(newFileOutputStream(raf.getFD(),UTF-8);out.write(HelloWorld!);out.flush();raf.seek(6);out.write(Java);out.flus
49、h();finally raf.close();v 例7.8的功能与例7.7一样,只不过是用RandomAccessFile来实现的。v 例7.8vimport java.io.*;vpublic class RandomDemo v public static void main(String args)v throws IOException v RandomAccessFilefa=new RandomAccessFile(data,rw);v fa.writeBoolean(true);v fa.writeInt(100);v fa.writeFloat(200.2f);v fa.se
50、ek(0);v boolean b=fa.readBoolean();v int i=fa.readInt();v float f=fa.readFloat();v System.out.println(The value read from a random file is:);v System.out.println(+b);v System.out.println(+i);v System.out.println(+f);v fa.close();v public RandomDemo()vv程序运行结果如图7.8所示。图 7.8 例程import java.io.*;class Cop