《Java程序设计》课件第7章_第1页
《Java程序设计》课件第7章_第2页
《Java程序设计》课件第7章_第3页
《Java程序设计》课件第7章_第4页
《Java程序设计》课件第7章_第5页
已阅读5页,还剩64页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第7章输入/输出7.1流和文件7.2基本输入/输出类7.3文件的输入/输出7.4编程实例 7.1流和文件

7.1.1流

Java语言中输入/输出功能是通过流类来实现的,java.io包提供了一套丰富的流类,可以完成从基本的输入/输出到复杂的随机文件访问,包括Java中的网络操作也是通过流来完成的。

流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件、内存或是网络连接。当程序需要写入数据的时候,就会开启一个通向目的地的流。可以想像,数据好像在其中流动,如图7.1所示。图7.1流的概念

Java中的流按照处理数据的单位可分为两种:一种是字节流,另一种是字符流,分别由四个抽象类InputStream、OutputStream、Reader和Writer来表示。Java中的其他多种多样的流类均是由它们派生出来的。早期的Java版本仅提供InputStream和OutputStream,它们是基于字节的流,而基于字符流的Reader和Writer是作为补充后来加入的。

本书主要介绍字节流的使用。字符流的使用与字节流十分相似,只是它们的读/写单位是Unicode字符,而字节流的读/写单位是字节。按照对流中数据的处理方式,Java语言中的流可分为文本流和二进制流。文本流是一个字符序列,在文本流中可按需要进行某些字符的转换,被读/写的字符和外部设备之间不存在一一对应的关系,被读/写字符的个数可能与外部设备中字符的个数不一样。例如标准输出流System.out就是文本流,程序中不同类型的数据经过转换后输出到标准输出设备。二进制流在读/写过程中不进行转换,外部设备中的字节(或字符)与被读/写的字节(或字符)一一对应。

由于Java输入/输出涉及的类非常多,本章首先介绍几个基本的抽象类,然后着重讨论文件的输入/输出操作。本书第8章将讨论部分有关网络编程的流类的使用。7.1.2文件

文件也是一个逻辑概念。计算机系统中的文件不仅指通常的磁盘文件,还包括很多外部设备,如键盘、显示器、打印机等,都可以看成是文件。

Java语言中对文件的读/写操作都是通过流来完成的。通过对文件的打开操作,可以建立流与特定文件之间的联系。可以使用输入流从文件里读出字节,并将这些字节保存到临时的字节数组里,或者使用输出流把它们写到新的文件里。值得注意的是,并不是所有的文件都具有相同的功能,例如,磁盘文件支持随机存取,而标准输入和标准输出只能顺序存取。

使用关闭操作,可以解除流与特定文件之间的联系。对于一个输出流,关闭流会使其相关的缓冲区中的所有内容写到外部设备。在程序终止前,应该关闭所有打开的流。 7.2基本输入/输出类

7.2.1InputStream类

InputStream是基本的输入流类,它是一个抽象类,程序中不可能直接创建InputStream类的对象,它定义了输入流类共同的特性。

InputStream类中定义了read方法,用于从输入流读取数据:

● publicabstractintread()throwsIOException;

● publicintread(byteb[])throwsIOException;

● publicintread(byteb[],intoffset,intlength)throwsIOException。

read方法有几种重载形式,可以读取一个字节或一组字节。若流中数据已读完,例如遇到磁盘文件尾,则返回-1。第三种形式的参数offset指将结果放在数组b[]中从第offset个字节开始的空间,length为字节长度。

InputStream类中还定义了其他一些基本的方法:

● publicintavailable()throwsIOException——返回输入流中可用的字节数。此方法对InputStream的有些派生类无效,会返回零字节的错误结果。

● publicvoidclose()throwsIOException——关闭输入流并释放资源。● publicbooleanmarkSupported();——返回布尔值,说明此流能否做标记。

● publicsynchronizedvoidmark(intreadlimit);——为当前流做标记。其参数说明在标记失效前可以读多少字节,这个值通常也就设定了流的缓冲区大小。

● publicsynchronizedvoidreset()throwsIOException——返回到上一次做标记处。

● publiclongskip(longn)throwsIOException——从输入流跳过几个字节。返回值为实际跳过的字节数。输入流只能从外部设备顺序读取数据,为了能重复读部分内容,提供“标记”(mark)这一机制,用于记录流中某些特定的位置。要支持mark,要求输入流有一定大小的缓冲区,用于存放部分数据,即从标记点到当前位置的数据。当这一缓冲区装满溢出,无法追踪到上一个标记处的数据时,标记失效。若用reset返回到一个失效的标记处,将会发生输入/输出异常(IOException)。7.2.2OutputStream类

OutputStream是基本的输出流类,与InputStream类一样也是抽象类,它定义了输出流类的共同特性。

OutputStream类定义了write方法,用于输出数据:

● publicabstractvoidwrite(intb)throwsIOException;

● publicvoidwrite(byteb[])throwsIOException;

● publicvoidwrite(byteb[],intoffset,intlength)throwsIOException。这三个重载形式都是用来向输出流写数据的。参数b为要输出的数据,第三种形式中offset、length参数的作用与输入流类的read方法类似。

其他方法主要有:

● publicvoidflush();——清除缓冲区,将缓冲区内尚未写出的数据全部输出。若要继承OutputStream类,这个方法必须重写,因为OutputStream中的方法未做任何实质性工作;

● publicvoidclose();——关闭输出流,释放资源。7.2.3PrintStream类

为了在标准输出流上提供更灵活方便的输出,Java语言定义了输出类PrintStream,标准输出流对象System.out就是PrintStream类的实例。

PrintStream类可以使用OutputStream类中定义的方法:

● publicvoidwrite(intb);

● publicvoidwrite(byteb[],intoffset,intlength);

● publicvoidflush();

● publicvoidclose()。更重要的是,PrintStream类提供了print和println方法,用于输出各种类型的数据(如int、double类型),并将各种不同类型的数据转换为字符串输出。

print方法的主要形式有:

● publicvoidprint(Objectobj);

● publicvoidprint(Strings);

● publicvoidprint(chars[]);

● publicvoidprint(charc);

● publicvoidprint(inti);

● publicvoidprint(longl);

● publicvoidprint(floatf);● publicvoidprint(doubled);

● publicvoidprint(booleanb)。

println方法与print方法形式相同,在输出时除输出数据外还输出一个换行符。println还有一个不带参数的形式:

publicvoidprintln()

该方法用于输出一个换行符。7.2.4其他常用流类

1.DataInputStream类与DataOutputStream类

InputStream类、OutputStream类定义了流类的基本特性,但是它提供的读/写数据的方法比较简单,只提供了一次读/写若干字节的功能,在实际使用时很不方便。

为了解决这个问题,Java输入/输出包中提供了数据输入流类(DataInputStream)与数据输出流类(DataOutput

Stream),对InputStream和OutputStream类进行包装,以InputStream和OutputStream类一次读/写若干字节的功能为基础提供了读/写各种类型数据的功能。数据输入流类DataInputStream类构造方法的形式为

publicDataInputStream(InputStream

in)

其中,参数in为本来的输入流对象。例如,下面的语句创建一个数据输入流类对象从标准输入流读取数据:

DataInputStreamkeyInput=newDataInputStream

(System.in);

DataInputStream类提供了读取各种类型数据的方法,例如:

● publicfinalintread(byte[]

b)throwsIOException;

● publicfinalintread(byte[]

b,int

off,int

len)throwsIOException;● publicfinalbooleanreadBoolean()throwsIOException;

● publicfinalbytereadByte()throwsIOException;

● publicfinalintreadUnsignedByte()throwsIOException;

● publicfinalshortreadShort()throwsIOException;

● publicfinalintreadUnsignedShort()throwsIOException;

● publicfinalcharreadChar()throwsIOException;

● publicfinalintreadInt()throwsIOException;

● publicfinallongreadLong()throwsIOException;

● publicfinalfloatreadFloat()throwsIOException;

● publicfinaldoublereadDouble()throwsIOException。

DataInputStream类是FilterInputStream类的子类,从FilterInputStream类中继承了skip、available、close、mark、read等方法,功能与InputStream类中同名方法类似,这里不再详细介绍。

DataOutputStream类用于数据的输出,其构造方法形式为

publicDataOutputStream(OutputStream

out)

其中,参数out为本来的输出流对象。

DataOutputStream类定义了很多方法,用于输出各种类型的数据,例如:

● publicfinalvoidwriteBoolean(boolean

v)throwsIOException;

● publicfinalvoidwriteByte(int

v)throwsIOException;

● publicfinalvoidwriteShort(int

v)throwsIOException;

● publicfinalvoidwriteChar(int

v)throwsIOException;

● publicfinalvoidwriteInt(int

v)throwsIOException;

● publicfinalvoidwriteLong(long

v)throwsIOException;

● publicfinalvoidwriteFloat(float

v)throwsIOException;

● publicfinalvoidwriteDouble(double

v)throwsIOException;

● publicfinalvoidwriteBytes(String

s)throwsIOException;● publicfinalvoidwriteChars(String

s)throwsIOException。

DtaOutputStream类是FilterOutputStream类的子类,从该类继承了close和write方法,write方法的功能及形式同OutputStream类的同名方法,close方法用于关闭输出流。

2.InputStreamReader类与OutputStreamWriter类

InputStream类与OutputStream类是字节流,而Java语言本身采用的是Unicode字符集,使用InputStream类与OutputStream类读/写双字节的中文信息有时会出现问题,不能正确处理。

Java语言输入/输出包从JDK1.1版开始提供了Reader类、Writer类读/写字符流,但是JDK1.1版以前的输入/输出功能都是通过字节流来实现的。为了能够处理这部分类型的流对象,JDK1.1版提供了InputStreamReader类与OutputStream

Writer类,它们分别是Reader、Writer类的子类,提供从字节流到字符流的转换。

InputStreamReader类的构造方法有四种形式:

● publicInputStreamReader(InputStream

in);

●publicInputStreamReader(InputStream

in,String

charsetName)throwsUnsupportedEncodingException;● publicInputStreamReader(InputStream

in,Charset

cs);

● publicInputStreamReader(InputStream

in,CharsetDecoder

dec)。

参数in为原来的字节流对象,charsetName、cs及dec均用于指定字符编码集。

InputStreamReader类提供了以下与InputStream类相似的方法,用于读取数据,不过它是以字符为单位的:

● publicintread()throwsIOException;

● publicintread(char[]

cbuf,int

offset,int

length)throwsIOException。

InputStreamReader类的其他常用的方法还有:

● publicbooleanready()throwsIOException——判断输入流是否已准备好,即是否可以读取数据;

● publicvoidclose()throwsIOException——关闭输入流。

OutputStreamWrite类的构造方法有四种形式:

● publicOutputStreamWriter(OutputStream

out);

● publicOutputStreamWriter(OutputStream

out,Charset

cs);

● publicOutputStreamWriter(OutputStream

out,CharsetEncoder

enc);●publicOutputStreamWriter(OutputStream

out,String

charsetName)throwsUnsupportedEncodingException。

参数out为原来的字节输出流,cs、enc、charsetName用于指定字符编码集。

对于中文信息的输入/输出,可采用相应的汉字编码集,例如:

InputStreamReaderin=newInputStreamReader(System.in,“GB2312”);

OutputStreamWriterout=newOutputStreamWriter

(System.out,“GB2312”);

OutputStreamWriter类常用的方法主要有下面几个:● publicvoidwrite(int

c)throwsIOException;

● publicvoidwrite(char[]

cbuf,int

off,int

len)throwsIOException;

● publicvoidwrite(String

str,int

off,int

len)throwsIOException。

以上三种方法用于向输出流输出数据,功能与OutputStream类的同名方法类似,不过是以字符为单位的。

● publiclongskip(long

n)throwsIOException——从输入流跳过几个字符。返回值为实际跳过的字符数;

● publicvoidflush()throwsIOException——刷新输出流;

● publicvoidclose()throwsIOException——关闭输出流。

3.BufferedReader类与BufferedWriter类

BufferedReader类与BufferedWriter类分别是Reader类和Writer类的子类,为Reader类对象和Writer类对象提供输入和输出缓冲区以提高输入/输出的效率。

BufferedReader类的构造方法形式为:

● publicBufferedReader(Reader

in);

● publicBufferedReader(Reader

in,int

sz)。

参数in为字符输入流对象,参数sz用于指定缓冲区大小。

除了从Reader类继承的方法外,BufferedReader类还提供了读取一行字符的方法:

publicStringreadLine()throwsIOException

BufferedWriter类的构造形式为:

● publicBufferedWriter(Writer

out);

● publicBufferedWriter(Writer

out,int

sz)。

参数out为字符输出流对象,sz指定缓冲区的大小。

除了从Writer类继承的方法外,BufferedWriter类还提供了在输出流中插入换行符的方法:

publicvoidnewLine()throwsIOException

在第8章的例子中读者将可以看到这里介绍的几个流类的例子。

7.3文件的输入/输出

7.3.1FileInputStream类

磁盘文件的输入/输出操作是Java语言中流类最基本的应用,磁盘文件的输入操作由FileInputStream类实现。

FileInputStream是文件输入流类,最常用的构造方法只需提供文件名即可,形式如下:

publicFileInputStream(StringfileName)throwsFileNot

FoundException

FileInputStream类是InputStream类的派生类,它覆盖了InputStream类中的read、skip、available、close等方法。程序7.1演示了磁盘文件的读取方法,运行该程序将显示FileInput.java文件的内容。【程序7.1】显示文本文件。

importjava.io.*;

publicclassFileInput

{

publicstaticvoidmain(String[]args)

{

bytebuffer[]=newbyte[2048];

try{

FileInputStreamfileIn=newFileInputStream("FileInput.java"); //创建FileInputStream类对象,打开文件

intbytes=fileIn.read(buffer,0,2048); //文件内容读入到buffer

Stringstr=newString(buffer,0,bytes); //利用buffer内容创建字符串

System.out.print(str); //输出字符串内容

}

catch(Exceptione){ System.out.println(e.toString());

}

}

}

7.3.2FileOutputStream类

FileOutputStream类提供了写文件的功能,它从Output

Stream派生而来。

FileOutputStream类最常用的构造方法与FileInputStream类似,只需提供文件名作参数,形式如下:

publicFileOutputStream(StringfileName)throwsFileNot

FoundException

FileOutputStream类覆盖了OutputStream类中的write、close、flush等方法。程序7.2演示了创建磁盘文件的方法,完成了磁盘文件的复制。

【程序7.2】复制文件。

importjava.io.*;

publicclassFileCopy

{

publicstaticvoidmain(String[]args)

{

if(args.length!=2){

System.out.println("命令行参数不正确"); }

try{

FileInputStreaminFile=newFileInputStream(args[0]); //打开源文件

FileOutputStreamoutFile=newFileOutputStream(args[1]);//打开目标文件

while(inFile.available()>0){

intc=inFile.read(); //从源文件读一字节

outFile.write(c); //写入到目标文件

} inFile.close(); //关闭源文件

outFile.close(); //关闭目标文件

System.out.println("文件复制成功");

}

catch(Exceptione){

System.out.println("文件复制失败");

}

}

}程序7.2从命令行获得源文件和目标文件名(保存在main方法的args参数中)。首先判断参数的个数,如果参数个数不为2,则显示出错信息后退出;如果参数个数正确,则

打开第一个参数(args[0])指定的文件,将其内容复制到第二个参数指定的文件。如果第二个参数指定的文件不存在,则创建一个新文件;如果该文件存在,则原来的内容被覆盖。

如果使用JDK调试程序7.2,运行该程序时可在命令行输入:

javaFileCopyFileCopy.javaFileCopy.bak其中,斜体字部分为传递给程序的命令行参数,上面的命令行表示将FileCopy.java复制到FileCopy.bak。

如果在JBuilder集成环境下调试该程序,可在设置运行配置的对话框中输入命令行参数,如图7.2所示。图7.2在JBuilder集成环境下设置调试命令行7.3.3RandomAccessFile类

FileInputStream与FileOutputStream类对磁盘文件的操作仅限于顺序读或顺序写,但很多时候希望访问文件中的某一块数据,或者按照某种逻辑顺序而不是数据在文件中存储的物理顺序访问文件,java.io包提供了RandomAccessFile类来实现磁盘文件的随机访问。

RandomAccessFile类不是InputStream或者OutputStream类的子类,但它定义了与InputStream和OutputStream类相似的read、write等方法,使用方法与FileInputStream、File

OutputStream类似。

RandomAccessFile类构造方法常用形式如下:

publicRandomAccessFile(StringFilename,Stringmode)throwsIOException

mode参数为文件读/写方式,用“r”表示只读,“rw”表示可读/写,与C语言文件打开的参数的含义类似。

与FileInputStream、FileOutputStream相比,Random

AccessFile的使用更灵活、更方便,定义了很多方法用于读/写各种类型的数据,例如:

● publicfinalbooleanreadBoolean()throwsIOException;

● publicfinalbytereadByte()throwsIOException;● publicfinalcharreadChar()throwsIOException;

● publicfinalshortreadShort()throwsIOException;

● publicfinalintreadInt()throwsIOException;

● publicfinaldoublereadDouble()throwsIOException;

● publicfinalfloatreadFloat()throwsIOException;

● publicfinalvoidwriteBoolean(booleanv)throwsIOException;

● publicfinalvoidwriteByte(bytev)throwsIOException;

● publicfinalvoidwriteChar(charv)throwsIOException;

● publicfinalvoidwriteShort(shortv)throwsIOException;

● publicfinalvoidwriteInt(intv)throwsIOException;● publicfinalvoidwriteDouble(doublev)throwsIOException;

● publicfinalvoidwriteFloat(floatv)throwsIOException。

其他主要方法成员还有:

● publicvoidseek(longpos);——将文件当前读/写位置移动到一个绝对地址,该地址是相对于文件头的偏移量。地址0表示文件的开头。

● longgetFilePointer();——返回文件当前读/写位置。

● longlength();——返回文件的长度。

● publicfinalStringreadLine();——从文件读取一行文本。程序7.3是一个使用RandomAccessFile类的简单例子,该程序以读/写方式打开一个已存在的文件,在文件的尾部添加一个字符串。

【程序7.3】RandomAccessFile类的使用。

importjava.io.IOException;

importjava.io.RandomAccessFile;

publicclassFileTest{

publicstaticvoidmain(Stringargs[])

{

RandomAccessFilemyRAFile;

Strings="InformationtoAppend\nHello!\n";

try{

myRAFile=newRandomAccessFile(“file1.txt”,“rw”); //打开文件

myRAFile.seek(myRAFile.length()); //移动到文件尾

myRAFile.writeBytes(s); //添加数据

myRAFile.close();

}catch(IOExceptione){

System.out.print(e.getMessage());

}

}

}7.3.4File类

File类并不是流类,但在处理磁盘文件时经常会用到,它可以完成文件的删除、创建等操作。

File类有两个经常会用到的与平台相关的属性。一个是seperatorChar,它是系统的名字分隔符,在UNIX平台上为“/”,在Windows平台上为“\”。另一个是路径分隔字符,在UNIX平台上为“:”,而在Windows平台上为“;”,如在Windows95中使用path命令设置路径时,多个文件夹名之间采用“;”分隔。

File类的构造方法有三种形式,分别根据文件名、文件路径与文件名、文件对象(目录)与文件名创建对象:

● publicFile(Stringpath);

● publicFile(Stringpath,Stringname);

● publicFile(Filedir,Stringname)。

习惯使用Windows平台的读者应注意,File类所指的文件包含文件和文件夹(子目录),可以使用File类的方法创建、删除和更名子目录。

File类常用的方法成员还有:

● publicbooleancanWrite();——测试文件和目录是否可写;

● publicbooleancanRead();——测试文件和目录是否可读;

● publicbooleanexists();——测试文件和目录是否存在;

● publicbooleandelete();——删除文件或目录,若删除目录,要求该目录必须为空;

● publicbooleancreateNewFile();——当且仅当该文件不存在时,创建一个空文件;● publicbooleanisDirectory();——判断File对象是否为目录;

● publicbooleanisFile();——判断File对象是否为文件;

● publicbooleanisHidden();——测试文件或目录是否隐含;

● publiclonglastModified();——获取文件或目录的最后修改时间;

● publicbooleansetLastModified(longtime);——设置文件或目录的最后修改时间;● publicString[]list();——得到当前目录下的所有文件名和目录名,若该File对象不是表示目录,则返回null;

● publicbooleanmkdir();——创建一个目录;

● publicbooleanmkdirs();——创建一个目录树,包括原来不存在的父目录;

● publicbooleanrenameTo(Filedest);——重命名文件或目录,成功返回true;

● publicbooleansetReadOnly();——将文件或目录设置为只读。

程序7.4使用File类列出当前目录下的所有文件和子目录名。【程序7.4】当前目录文件列表。

importjava.io.File;

publicclassDirList{

publicstaticvoidmain(String[]args){

Filepath=newFile(".");

String[]list=path.list();

for(inti=0;i<list.length;i++)

System.out.println(list[i]);

}

}【程序7.5】File类的文件管理功能演示。

importjava.io.*;

publicclassdemofile

{

privatefinalstaticStringusage=

"Usage:demofilepath1...\n"+

"Createeachpath\n"+

"Usage:demofile-dpath1...\n"+

"Deleteseachpath\n"+

"Usage:demofile-rpath1path2\n"+

"renamesfrompath1topath2\n"; privatestaticvoidusage()

{

System.err.println(usage);

System.exit(1);

}

privatestaticvoidfileData(Filef)

{

try{

System.out.println("Absolutepath:"+f.getAbsolutePath()+ “\r\nCanread:”+f.canRead()+

“\r\nCanwrite:”+f.canWrite()+

“\r\ngetName:”+f.getName()+

“\r\ngetParent:”+f.getParent()+

"\r\ngetPath:"+f.getPath()+

"\r\ngetCanonicalPath:"+f.getCanonicalPath()+

"\r\ntostring:"+f.toString()); if(f.isFile())

System.out.println("itisafile");

elseif(f.isDirectory())

System.out.println("itisadirectory");

}catch(Exceptione){

Stringerr=e.toString();

System.out.println(err);

}

}

publicstaticvoidmain(String[]args) {

if(args.length<1)

usage();

if(args[0].equals("-r")){

if(args.length!=3)usage();

Fileold=newFile(args[1]);

Filername=newFile(args[2]);

old.renameTo(rname);

fileData(old);

fileData(rname);

return; }

intcount=0;

booleandel=false;

if(args[0].equals("-d")){

count++;

del=true;

}

for(;count<args.length;count++){

Filef=newFile(args[count]);

if(f.exists()){

System.out.println(f+"Exists"); if(del){

System.out.println("deleting..."+f);

f.delete();

}

}

else{

if(!del){

f.mkdirs();

System.out.println("created"+f); }

}

fileData(f);

}

}

}

程序7.5使用File类实现了目录的创建、删除和重命名,该程序从命令行获取参数,然后执行相应的操作。例如,输入命令:

javademofilenewdir1newdir2斜体部分为传递给命令行的参数,即在当前目录下创建newdir1和newdir2子目录。

输入命令:

javademofile–dnewdir1

将删除newdir1子目录。

输入命令:

javademofile–rnewdir2newdir3

将子目录newdir2命名为newdir3。

7.4编程实例

最后再来看一个例子,该程序将文件text.src的内容连接到text.des文件原有内容的后面,然后显示文件text.des的有关信息,最后显示文件的内容。

【程序7.6】文件的连接。

importjava.io.*;

publicclassfileUnion{

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论