版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
9.1文件管理
9.2字节流和字符流
9.3RandomAccessFile类9.4标准I/O
9.5小结
9.6习题
9.1.1File类
1.文件操作实例
【例9-1】指定并显示目录下所有的文件名。
假设“D:\student”的目录结构如图9-1所示,需要得到图9-2中的结果。9.1文件管理图9-1指定目录下的结构图9-2要求得到的统计信息这个操作有三个关键点:①如何确定指定目录?②如何筛选出该目录下的文件?
③怎样得到文件名或目录名并显示?利用File类就可以解决上面的问题。
程序清单如下:
importjava.io.*;//File类位于这个包中
publicclassFileDir
{//利用StringBuffer类存放不断取出的信息
StringBufferallDirectorys;//存放目录名信息
StringBufferallFiles;//存放文件名信息publicFileDir()
{allDirectorys=newStringBuffer();
allFiles=newStringBuffer();
}
publicvoidgetInformation()
{Filedir=newFile(“D:\\student”);
//用dir指定要操作的目录
Filea[]=dir.listFiles();
//以File对象形式得到该目录下的所有文件(包括子目录)inti=0,j=0;
for(intk=0;k<a.length;k++)
{if(a[k].isDirectory())//判断是否是目录
allDirectorys.append(a[k].getName()+"\n");
if(a[k].isFile())//判断是否是文件
allFiles.append(a[k].getName()+"\n");
}
Stringstr1=newString(allDirectorys);//将BufferString对象处理成字符串Stringstr2=newString(allFiles);
System.out.println("该目录下的文件夹有:\n"+str1);
System.out.println("该目录下的文件有:\n"+str2);
}
publicstaticvoidmain(String[]args)
{FileDirfd=newFileDir();
fd.getInformation();
}
} 程序中,File类解决了以下关键问题:
(1) Filedir=newFile(“D:\\student”);
利用File类的构造方法,使得dir对象指向D:\student目录,即操作对象被确定下来。其中“\\”是目录分隔符。
(2) Filea[]=dir.listFiles();
通过dir对象调用File类的listFiles()方法,得到该目录下所有文件和子目录的抽象路径名(返回类型是File),并存储到数组里。之后就可以操作数组元素,依次处理每个文件。
(3) a[k].isDirectory()和a[k].isFile()方法的执行,可判断数组元素里存储的抽象路径名给定的文件是普通文件还是目录。
2.File类的基本操作
在进行文件操作时,需要知道一些关于文件的信息。File类提供了一些方法来操纵文件和获得文件的信息。对于目录,Java把它当作一种特殊的文件,即文件名的列表。通过File类的方法,可以得到文件或目录的描述信息,包括名称、所在路径、读/写性、长度等,还可以进行创建新目录、创建临时文件、改变文件名、删除文件、列出一个目录中所有的文件或与某个模式相匹配的文件等操作。
1)构造方法
File类的构造方法见表9-1。表9-1File类的构造方法其中,路径名既可以是字符串,也可以是File对象。
【例9-2】File类的构造方法应用(假设“D:\student\天使宝贝”目录结构如图9-3所示)。
importjava.io.*;
publicclassTestFile
{publicstaticvoidmain(String[]args)
{Filedir=newFile(“d:\\student”);//创建一个父路径
Filef1=newFile(dir,“2008-2-1.jpg”);//指定一个文件
Filef2=newFile(“d:\\student”,“天使宝贝”);
//指定一个子目录图9-3“D:\student\天使宝贝”的目录结构
Stringstr1,str2[];
str1=f1.getPath();//得到字符串路径名
str2=f2.list();//得到目录列表中文件名的字符串形式,存储到数组中
System.out.println(“\nf1可操作的对象是:”);
System.out.println(str1);
System.out.println(“\nf2可操作的对象是:”);
for(inti=0;i<str2.length;i++)
System.out.print(str2[i]+“\t”);
}
}
程序运行结果如图9-4所示。图9-4运行结果
2) File类提供的方法
创建一个文件对象后,可以用File类提供的方法来获得文件相关信息,并对文件进行操作。表9-2列举了一部分File提供的方法。表9-2File类提供的方法
【例9-3】创建目录,构造文件。假设“D:\example”目录结构如图9-5所示,现在要建立它的一个子目录“temp”,并且在这个子目录里创建一个新文件“ok.java”,不含任何内容,如图9-6所示。图9-5“d:\example”的目录结构图9-6运行结果程序清单如下:
importjava.io.*;
publicclassFileAction
{publicstaticvoidmain(String[]args)
{FilenewPath=newFile("d:\\example\\temp");
FilenewFile=newFile("d:\\example\\temp\\Ok.java");
newPath.mkdir();//建立temp目录System.out.println("Creatdirectorysuccessfully!");
try//建立新文件ok.java
{newFile.createNewFile();
}
catch(Exceptione){}
System.out.println("Creatfilesuccessfully!");
}
}9.1.2文件过滤器
1.FileFilter和FilenameFilter接口
Java提供了两个接口FileFilter和FilenameFilter来实现对文件名字符串的过滤。这两个接口中都有accept()方法。
(1) FileFilter接口中的accept()方法:
publicinterfaceFileFilter
{publicbooleanaccept(Filepathname);
}
(2) FilenameFilter接口中的accept方法:
publicinterfaceFilenameFilter
{publicbooleanaccept(Filedir,Stringname);
}
FileFilter和FilenameFilter接口的区别在于,其中accept()方法的参数不同。
2.显示文件清单时使用过滤器
使用File类的list()方法和listFiles()方法显示文件清单时,可以设置一个文件过滤器作为参数(如表9-2中最后四个方法所示)。当调用list()方法或listFiles()方法时,原始列表中的每个项目将调用accept()方法。如果accept()方法返回true,则相应的项目就留在列表内;如果返回false,则相应的项目将从列表中删除。显然,提供accept()方法的接口成为使过滤器机制运转起来的载体,因此需要定义自己的类来实现适当的接口,以获得具有特定扩展名或者以特定字符序列开始的文件名列表。
【例9-4】使用过滤器对指定文件进行过滤。
假设“D:\student”目录结构如图9-7所示,现在要将该目录下所有扩展名为“mp3”的文件显示出来。在这个过程中对目录下的文件名要进行筛选,将符合要求的文件存储起来。利用文件过滤器就可以实现这个功能,操作的关键点有如下两个:
(1)如何实现接口中的accept()方法?
(2)怎样运用过滤机制?图9-7“d:\student”目录的结构程序清单如下:
importjava.io.*;
publicclassDirFilterimplementsFilenameFilter
{publicbooleanaccept(Filedir,Stringname)
{booleanboo=false;
intstart=name.indexOf('.'); //确定文件名中 '.' 的位置
Stringsuffix=name.substring(start+1); //截取文件扩展名
if(suffix.equalsIgnoreCase("mp3")) //扩展名忽略大小后与 "mp3" 比较
boo=true;
returnboo;
}publicstaticvoidmain(String[]args)
{Stringresult[];
Filedir=newFile(“d:\\student”);
result=dir.list(newDirFilter());
//实现文件过滤,结果保存到数组中
System.out.println("\n后缀是\'mp3\'的文件如下:");
for(inti=0;i<result.length;i++)
System.out.println(result[i]);
}
}
程序运行的结果如图9-8所示。图9-8运行结果程序中,DirFilter类是一个自定义的文件名过滤器类,实现了FilenameFilter接口。类中的accept()方法完成了文件扩展名的截取和比较,返回逻辑值。dir对象在调用list()方法时通过参数设置了过滤器,list()方法通过为此目录对象下的每个文件名调用accept(),来判断该文件是否包含在内;判断结果由accept()返回的布尔值表示。9.2.1流机制
I/O类库中常使用“流”这个抽象概念,它代表任何有能力输出数据的数据源对象或者是有能力接受数据的接受端对象。
9.2字节流和字符流
Java的输入/输出流提供了一条通道:可以利用输入流将数据从“源头”读进来,利用输出流将数据写到目的地,如图9-9和图9-10所示。流通过Java的输入/输出系统与物理设备链接,尽管物理设备不尽相同,但是所有流的行为具有同样的方式,能够适应所有类型的外部设备。创建一个好的输入/输出(I/O)系统是一项艰难的任务。Java类库的设计者通过创建大量的类来解决这个难题,使得“流”屏蔽了实际的I/O设备中处理数据的细节。图9-9输入流示意图图9-10输出流示意图
Java类库中的I/O类分为输入和输出两部分。通过继承,任何自InputStream或Reader派生而来的类都含有名为read()的基本方法,用于读取单个字节或者字符。同样,任何自OutputStream或Writer派生而来的类都含有名为write()的基本方法,用于写单个字节或者字符。根据读/写数据的机制,可以分成两种类型的数据流:二进制字节流(BinaryStream)和字符流(CharacterStream)。表9-3列出了java.io包中数据流的抽象类。表9-3java.io包中数据流的抽象类
1.字节流InputStream和OuputStream
两者均为所有面向字节的输入/输出流的超类。类中声明了用于字节输入/输出的多个方法,包括读取数据、写入数据、标记位置、获取数据量、关闭数据流等。
InputStream类别的类从不同数据源产生输入,这些数据源包括:
(1)字节数组。
(2) String对象。
(3)文件。
(4)“管道”,其工作方式与实际管道相似,即从一端输入,从另一端输出。
(5)一个由其他种类的流组成的序列,以便将它们收集合并到一个流内。
(6)其他数据源,如Internet连接等。
OutputStream类决定了输出的目标:字节数组、文件或管道。
2.字符流Reader和Writer
两者均为所有面向字符的输入/输出流的超类。设计Reader和Writer继承层次结构主要是为了国际化。原有的I/O流继承层次结构仅支持8位的字节流,并且不能很好地处理16位的Unicode字符。因为Unicode用于字符国际化,所以添加Reader和Writer继承层次结构就是为了在所有的I/O操作中都支持Unicode。两者的使用方法与InputStream类和OutputStream类基本相同。不同的是,这两个类以Unicode字符为单位进行读/写,当写入一个16位的Unicode字符时,按字节分成两部分,先写高位字节,后写低位字节。
Reader类从字符数组、String对象、文件和管道等数据源产生输入。Writer类决定了输出目标:字符数组、字符缓冲区、文件或管道。
下面将讲解部分I/O流类,文中提供了类的常用方法,其他方法可参阅JDKAPI文档。9.2.2字节流类
1.ByteArrayInputStream和ByteArrayOutputStream
可以使用ByteArrayInputStream类打开一个来自内存中的字节数组的输入流。下面展示了ByteArrayInputStream类的继承关系:
ByteArrayInputStream类的构造方法见表9-4,它的方法见表9-5。表9-4ByteArrayInputStream类的构造方法表9-5ByteArrayInputStream类的方法
ByteArrayOuputStream类允许将字节流写入缓冲区。下面展示了ByteArrayOutputStream类的继承关系:
ByteArrayOutputStream类的构造方法见表9-6,它的方法见表9-7。表9-6ByteArrayOutputStream类的构造方法表9-7ByteArrayOutputStream类的方法【例9-5】完成字节数组输入流与输出流的操作。
importjava.io.*;
publicclassInByteArray
{publicstaticvoidmain(String[]args)throwsIOException
{Stringstr="PleasestudyI/O!";
byte[]a=str.getBytes();//将字符串转化成字节数组
byte[]b;
intn;//定义一个字节数组输入流,数据源是字节数组a
ByteArrayInputStreamin=newByteArrayInputStream(a);
System.out.println("\nDatafromByteArraya:");
//从数组a逐字节地读数据,并以字符形式输出
while((n=in.read())!=-1)
System.out.print((char)n);
System.out.println();
//定义一个字节数组输出流
ByteArrayOutputStreamout=newByteArrayOutputStream();
out.write(a);
//将数组a中的全部字节写到这个数组输出流中
b=out.toByteArray();
//创建一个新分配的byte数组b,数据来自输出流
//从数组b逐字节地读数据,并以字符形式输出
System.out.println("\nDatafromByteArrayb:");
for(inti=0;i<b.length;i++)
System.out.print((char)b[i]);
in.close();//关闭输入流,释放系统资源
}
}
运行结果如图9-11所示。图9-11程序运行结果
2.FileInputStream和FileOutputStream
FileInputStream类专为处理来自文件的面向字节的输入而设计,它的继承关系如下:FileInputStream类的构造方法见表9-8,它的方法见表9-9。表9-8FileInputStream类的构造方法表9-9FileInputStream类的方法
FileOutputStream类可以逐字节地将数据写到文件中,它的继承关系如下:FileOutputStream类的构造方法见表9-10,它的方法见表9-11。表9-10FileOutputStream类的构造方法表9-11FileOutputStream类的方法
【例9-6】完成文件的读操作。
文件t1.txt的内容如图9-12所示,要求将其内容读出来并在控制台中显示,运行结果如图9-13所示。图9-12“t1.txt”文件的内容图9-13程序运行结果程序清单如下:
importjava.io.*;
publicclassInByteFile
{publicstaticvoidmain(String[]args)
{intnum=0;
intb;//用于接收in.read()的返回值
try
{//把当前目录下的文件t1.txt作为数据源,建立输入流
FileInputStreamin=newFileInputStream("t1.txt");
System.out.println("\n文件t1.txt的内容如下:\n");//逐字节地读文件,依次返回字节值
while((b=in.read())!=-1)
{System.out.print((char)b);//按字符形式输出
num++;
//统计字节个数
}
System.out.println();
System.out.println("TOTAL="+num);in.close();//关闭输入流,释放系统资源
}
catch(Exceptione){};
}
}
【例9-7】完成图片文件的读/写操作。
“D:\java”目录结构如图9-14所示,其包含一个图片文件“1.jpg”。现在要建立一个新文件,取名为“new.jpg”,内容来自“1.jpg”。图片内容见图9-15,成功读/写数据后的目录结构见图9-16,这时打开文件“new.jpg”,与图9-15的形式完全一样。图9-14“D:\java”目录结构图9-15“1,jpg”文件内容
图9-16运行后的目录结构程序清单如下:
importjava.io.*;
publicclassRWPicture
{publicstaticvoidmain(String[]args)
{try
{FileInputStreamin=newFileInputStream(“1.jpg”);
//建立文件输入流
FileOutputStreamout=newFileOutputStream(“new.jpg”);
//建立文件输出流
intcount=in.available();
//得到了文件1.jpg的字节数
byte[]b=newbyte[count];
in.read(b);
//将1.jpg文件内容读到字节数组b中
out.write(b);//将字节数组b中的内容写到文件new.jpg中
in.close();
//关闭输入、输出流,释放系统资源
out.close();
System.out.println("成功创建new.jpg文件,请查看!");
}
catch(Exceptione){};
}
}
FileOutputStream类在创建输入流时要指定文件,有可能出现文件不存在、打不开、读不了的情况,因此要捕获异常。在利用输出流对象进行写操作时,如果文件不存在,则创建一个新文件;如果文件已存在,使用重写方式则会覆盖原有数据。
3.FilterInputStream和FilterOutputStream
在直接使用扩展子类的方法时,如果导致产生了大量的、用以满足所需的各种可能的组合的子类,通常会使用修饰器,但处理太多的子类时就显得不太实际。修饰器模式提供了相当多的灵活性,但同时也增加了代码的复杂性。JavaI/O类库操作不便的原因在于:必须要创建很多类——“核心”I/O类加所有的修饰器,才能得到所要求的单个I/O对象。
FilterInputStream和FilterOutputStream是用来提供修饰器类接口以控制特定输入流(InputStream)和输出流(OutputStream)的两个类,定义如下:
publicclassFilterInputStreamextendsInputStream
publicclassFilterOutputStreamextendsOutputStream
这两个类能为所有正在被修饰的对象提供通用接口,是修饰器的必要条件。通过FilterInputStream可以从InputStream读取数据,通过FilterOutputStream可以向OutputStream写入数据。这个意义可以从他们子类的构造方法上得到体现。
FilterInputStream类型见表9-12,FilterOutputStream类型见表9-13。表9-12FilterInputStream类型表9-13FilterOutputStream类型DataInputStream类和DataOutputStream类的继承关系如下所示:
DataInputStream类及DataOutputStream类的构造方法见表9-14,类方法见表9-15。表9-14DataInputStream类和DataOutputStream类的构造方法表9-15DataInputStream类和DataOutputStream类的部分方法
【例9-8】DataInputStream类和DataOutputStream类的操作。
“D:\example”目录结构如图9-17所示。建立一个文件“infor.dat”,存放一些基本类型数据;并将该文件的数据读进来,在控制台按照数据类型正确显示数据。程序运行后,目录变化如图9-18所示。图9-17“D:\example”目录结构图9-18运行后的目录结构程序清单如下:
importjava.io.*;
publicclassFilter_Data
{publicstaticvoidmain(String[]args)
{try
{//建立文件输出流对象,目标为infor.dat
FileOutputStreamout1=newFileOutputStream("infor.dat");//建立一个指向out1的输出流,按照DataOutputStream类提供的方法将数据写到out1流中
DataOutputStreamout2=newDataOutputStream(out1);
//将数据写到文件中去
out2.writeInt(300); out2.writeInt(9999);
out2.writeFloat(123.45f); out2.writeBoolean(true);
out2.writeBoolean(false); out2.writeChars("filter___DataOutputStream");
}catch(IOExceptione){}
try
{//建立文件输入流对象,数据源为infor.dat
FileInputStreamin1=newFileInputStream("infor.dat");
//建立一个指向in1的输入流,按照DataInputStream类提供的方法从in1流中读取数据
DataInputStreamin2=newDataInputStream(in1);
//从文件中读出数据并在控制台显示
System.out.println("thecontentof\'infor.dat\'are:");
System.out.println("整数1:\t"+in2.readInt());
System.out.println("整数2:\t"+in2.readInt());
System.out.println("float型:\t"+in2.readFloat());
System.out.println("boolean型1:\t"+in2.readBoolean());
System.out.println("boolean型2:\t"+in2.readBoolean());
System.out.print("字符串:\t");charch;
while((ch=in2.readChar())!='\0')
System.out.print(ch);
}catch(IOExceptione){}
}
}
控制台显示如图9-19所示。图9-19运行后的显示结果
PrintStream类以一种便利的方式将各种数据类型的数据打印至另一个作为接收端的输出流中,即将各种数据类型的数据转换成字符串写入接收端输出流。当数据被写到缓冲区后,调用println()方法或写入一个换行符,PrintStream对象的flush()方法将自动执行,并刷新缓冲区,即可将缓冲区中的数据写入接收端输出流中。
PrintStream类的继承关系如下:PrintStream类的部分构造方法见表9-16,类方法见表9-17。表9-16PrintStream类的构造方法表9-17PrintStream类的方法
【例9-9】PrintStream类的操作。
“D:\example”目录结构如图9-20所示。建立一个文件“infor.txt”用于存放数据。执行后的目录变化如图9-21所示,文件“infor.txt”内容如图9-22所示。图9-20 “D:\example”目录结构图9-21程序执行后的目录结构图9-22 “infor.txt”文件的内容程序清单如下:
importjava.io.*;
publicclassFilter_Print
{publicstaticvoidmain(String[]args)
{try
{StringfileName="d:\\example\\infor.txt";//定义目标的字符串形式//定义输出流,以fileName为目标且输出内容可以附加到文件末尾
FileOutputStreamout1=newFileOutputStream(fileName,true);
//定义一个指向out1的输出流,可以按照PrintStream类提供的方法将数据写到out1流中
PrintStreamout2=newPrintStream(out1);//进行数据输出
char[]c={'奥','运','精','神'};
out2.print(c);
out2.println(true);
out2.print("祖冲之与圆周率:");
out2.println(3.1415926);
out2.print("利率:");
out2.print(5);out2.write(37);//该方法使得字节数据37对应于ASCII码的'%'
out2.println();
out2.println("打印输出流对象自身:");
out2.print(out2);
}
catch(IOExceptione)
{e.printStackTrace();
}
}
}
PrintStream类的方法比较简单,使用时应注意用write()方法写数据与用print()/println()方法打印数据之间的区别。另外,执行该类的方法后,目标文件中的内容是可见的,这是与DataOutputStream对象写入文本文件数据明显不同的地方。9.2.3字符流类
1.FileReader和FileWriter
可以使用FileReader类创建从文件进行读取的基于字符的流,它的继承关系如下:FileReader类的构造方法见表9-18。表9-18FileReader类的构造方法这个类只定义了构造方法,此外只具有从InputStreamReader继承的功能。表9-19列举了FileReader父类的一些常用方法。表9-19FileReader父类的常用方法
FileWriter类可用于创建写入文件的基于字符的流,它的继承关系如下:FileWriter类的构造方法见表9-20。表9-20FileWriter类的构造方法
FileWriter类只定义了构造方法,此外只具有从InputStreamWriter继承的功能。表9-21列举了父类的一些常用方法。表9-21FileWriter父类的常用方法
【例9-10】读取基于字符的文件。
打开一个文件“D:\example\file.txt”,内容见图9-23。将文件内容读到缓冲区,然后显示数据,见图9-24。图9-23文件“file.txt”的内容图9-24程序执行后的结果程序清单如下:
importjava.io.*;
publicclassInFileReader
{publicstaticvoidmain(String[]args)throwsException
{FileReaderfr=newFileReader(“d:\\example\\file.txt”);
//构造一个输入流
chardata[]=newchar[200];//用来存储数据
intcharNumber=fr.read(data);
//从流中读取数据写到data中,并返回读入的字符数
Stringstr=newString(data,0,charNumber);
//将字符数组中的数据转化成字符串System.out.println(“\n文件内容如下:”);
System.out.println(str);
System.out.println(“\n字符个数为:”+charNumber);
}
}
【例9-11】将数据写到文件中。
使用FileWriter将字符缓冲区中的数据写到文件中,可采用三种方式:逐字符地写数据、一次写所有数据、分批写数据,分别对应文件“D:\example\infor1.txt”、“D:\example\infor2.txt”和“D:\example\infor3.txt”,运行结果见图9-25、图9-26和图9-27。图9-25 “inforl.txt”文件的内容图9-26 “infor2.txt”文件的内容图9-27 “infor3.txt”文件的内容程序清单如下:
importjava.io.*;
publicclassOutFileWriter
{publicstaticvoidmain(String[]args)throwsException
{chardata[]={‘心','情','愉','快','地','学','习','J','a','v','a','!'};
//数据源
FileWriterfw1=newFileWriter("d:\\example\\infor1.txt");
//构造第一个输出流
FileWriterfw2=newFileWriter("d:\\example\\infor2.txt");//构造第二个输出流
FileWriterfw3=newFileWriter("d:\\example\\infor3.txt");//构造第三个输出流for(inti=0;i<data.length;i++)
fw1.write(data[i]);//逐字符写
fw2.write(data);//一次性写
fw3.write(data,5,7);//从数组的第5个位置连续写7个字符
fw1.close();//只有关闭流的时候才发生了写文件操作
fw2.close();
fw3.close();
}
}
2.BufferedReader和BufferedWriter
很多时候需要逐行操作文本文件的内容,BufferedReader和BufferedWriter类提供了这样的操作方法,使得问题解决起来更简单、更便捷。
BufferedReader和BufferedReader类的继承关系如下:BufferedReader类的构造方法见表9-22,类方法见表9-23。表9-22BufferedReader类的构造方法表9-23BufferedReader类的方法BufferedWriter类的构造方法见表9-24,类方法见表9-25。表9-24BufferedWriter类的构造方法表9-25BufferedWriter类的方法
【例9-12】文本文件的读写。
文件“D:\example\source.txt”的内容如图9-28所示,现将它的内容写到当前目录下的文件“destnation.txt”中,结果见图9-29。图9-28文件“source.txt”的内容图9-29文件“destnation.txt”的内容程序清单如下:
importjava.io.*;
publicclassBuffered_IO
{publicstaticvoidmain(String[]args)
{Strings=newString();
try
{FileReaderfr=newFileReader(“source.txt”);
FileWriterfw=newFileWriter(“destnation.txt”);
BufferedReaderin=newBufferedReader(fr);
//建立一个输入流指向in
BufferedWriterout=newBufferedWriter(fw);
//建立一个输出流指向outout.write(“thefollowingisfromsource:”);
//给目标文件开始处加一行信息
out.newLine(); //写一个换行符
while((s=in.readLine())!=null)
//读取一行文本,不为空时完成写功能
{out.write(s); //写目标文件
out.newLine();
}
in.close();out.close();//关闭输出流,将缓冲中的数据写到目的文件中
System.out.println("成功创建destnation.txt文件,请查看!");
}
catch(Exceptione){};
}
}
BufferedReader类的readLine()方法只是读入一行数据,但并不提供换行功能,只能再借助newLine()方法写入一个换行符。下面利用PrintWriter类的方法可以将这两个功能结合在一起,详细内容请参考JDKAPI中关于该类的使用方法。
程序改动如下:
importjava.io.*;
publicclassBuffered_IO_2
{publicstaticvoidmain(String[]args)
{Strings=newString();try{BufferedReaderin=newBufferedReader(newFileReader("source.txt"));
PrintWriterout=newPrintWriter(newFileWriter("destnation.txt"));
out.println("thefollowingisfromsource");
while((s=in.readLine())!=null)
out.println(s);
in.close();
out.close();
System.out.println("成功创建destnation.txt文件,请查看!");
}catch(Exceptione){}
}
}
1.思考一个问题
当一个文件由大小已知的记录组成,需要从一条记录转移到另一条记录时该如何操作?对一个文件既能读又能写,该如何操作?
针对以上要求,可由搜寻机制来实现。有些类,如BufferedInputStream允许标注(mark())位置(其值存储在内部某个简单变量)和重新设定位置(reset()),但是这些功能有限。Java的I/O流机制总是分别建立输入流和输出流,如何在一个流中完成读/写操作,RandomAccessFile类正好解决了上述问题。9.3RandomAccessFile类
RandomAccessFile类适用于由大小已知的记录组成的文件,它支持搜寻方法,并且只适用于文件。可以使用seek()方法将记录从一处转移到另一处,然后读取或者修改记录。实际上文件中记录的大小不一定都相同,只要能够确定那些记录有多大以及它们在文件中的位置即可。
RandomAccessFile类的继承关系如下:
RandomAccessFile类的定义如下:
publicclassRandomAccessFile
extendsObject
implementsDataOutput,DataInput,Closeable
可以看出,RandomAccessFile类既不是字节流继承层次结构中的一部分,也不是字符流继承层次结构中的一部分。除了实现了DataInput和DataOutput接口之外,它和这两类的继承层次结构没有任何关联,它是一个完全独立的类。
2.RandomAccessFile类的使用
RandomAccessFile类的构造方法见表9-26,类方法见表9-27。表9-26RandomAccessFile类的构造方法表9-27RandomAccessFile类的方法续表从本质上来说,RandomAccessFile的工作方式类似于把DataInputStream和DataOutputStream组合起来使用,还添加了一些方法。其中,getFilePointer()方法用于查找当前所处的文件位置,seek()方法用于在文件内移至新的位置,length()方法用于判断文件的最大尺寸。另外,在构造方法中还需要第二个参数指示“随机读”(r)还是“既读又写”(rw),它并不支持只写文件。
【例9-13】文件读写。
“D:\example\names.txt”文件内容如图9-30所示。通过程序再添加两个动物名称,并在控制台中显示,如图9-31和图9-32所示。图9-30原文件的内容图9-31运行后的文件内容图9-32控制台显示结果程序清单如下:
importjava.io.*;
publicclassRandom_RW
{publicstaticvoidmain(String[]args)
{Stringstring;
Stringarray[]=newString[256];
longlen=0;
inti=0,counter=0;
try{//以既读又写的方式建立一个数据流,源为names.txt文件
RandomAccessFileaccess=newRandomAccessFile(“names.txt”,“rw");
len=access.length();
//统计文件长度(按字符个数计算),回车换行统计为2个字符
access.seek(len);
//设置指针到下一个写操作的位置(从位置0算起)
access.writeBytes("fox\n");
//按字节序列将一个字符串写到这个文件中
access.writeBytes("bee\n");
access.seek(0);//将指针重新定位到文件的起始位置
while((string=access.readLine())!=null)
//行读,结果记录到string
{counter++; //记录行数
array[i++]=string;
//读出的数据(字符串)存储到数组中
}access.close();
}
catch(IOExceptionex){}
for(i=0;i<counter;i++) //显示数组信息
System.out.println(array[i]);
}
}
【例9-14】教材书目管理。
教材信息存放在“D:\example\bookinfor.txt”文件中,假设已存储了一些数据资料,此时运行该管理系统,界面如图9-33所示。要求从界面录入新的数据记录,当单击“增加”按钮时,将信息以追加方式存入到文件中,并且刷新列表,结果如图9-34所示。图9-33对已有数据的显示
图9-34增加新数据程序清单如下:
importjava.io.*;
importjava.awt.*;
importjavax.swing.*;
importjava.awt.event.*;
publicclassRandom_BookextendsJFrameimplementsActionListener
{//定义界面元素JButtonbt=newJButton("增加");
JTextFieldtf1=newJTextField(15);
JTextFieldtf2=newJTextField(15);
JTextFieldtf3=newJTextField(15);
JTextAreata=newJTextArea(7,20);
JLabellb1=newJLabel("编号");
JLabellb2=newJLabel("名称");
JLabellb3=newJLabel("作者");RandomAccessFileaccess;
Stringstr;
publicvoidinit()throwsFileNotFoundException//界面初始化
{Containercp=getContentPane();
FlowLayoutlayout=newFlowLayout();
cp.setLayout(layout);
cp.add(ta);
cp.add(lb1);cp.add(tf1);
cp.add(lb2);cp.add(tf2);cp.add(lb3);cp.add(tf3);
cp.add(bt);
bt.addActionListener(this);//为按钮注册监听者对象
ta.setEditable(false);
setSize(250,400);
setVisible(true);
access=newRandomAccessFile("bookinfor.txt","rw");
//创建数据流
try{while((str=access.readUTF())!=null)//以UTF-8格式读取一个字符串
ta.append(str+"\n");
}catch(IOExceptionex){};
}
publicvoidactionPerformed(ActionEvente)
{Stringstr1=tf1.getText()+""+tf2.getText()+""+tf3.getText()+"\n";
Stringstr2=tf1.getText()+""+tf2.getText()+""+tf3.getText();
ta.append(str1);
tf1.setText("");tf2.setText("");tf3.setText("");
try{longlen=access.length();
access.seek(len);//指针定位到写数据位置
//以UTF-8格式写入一个字符串,与readUTF()方法配合可以正确读出汉字
access.writeUTF(str2);
}catch(IOExceptionex){};
}publicstaticvoidmain(String[]args)throwsException
{Random_BookwFile=newRandom_Book();
wFile.init();
wFile.addWindowListener(newWindo());
//为窗口注册监听者对象
}
}classWindoextendsWindowAdapter
{publicvoidwindowClosing(WindowEvente)
{System.exit(0);
}
}
说明:利用FileWriter类也可以完成数据的追加,请读者自己尝试。标准I/O参考了Unix中“程序所使用的单一信息流”概念,而Windows等其他操作系统通过不同的方式实现了同样的概念。程序的所有输入都可以来自于标准输入,它的所有输出也都可以发送到标准输出,以及所有的错误信息都可以发送到标准错误。标准I/O的意义在于:一个程序的标准输出可以成为另一程序的标准输入。9.4标准I/O按照标准I/O模型,Java提供了System.in、System.out和System.err。其中:System.in作为标准输入,System.out作为标准输出,System.err作为标准错误。Java通过系统类System实现了标准输入/输出的功能,它包含在java.lang包中,继承关系如下:同时,System类被声明为一个final类,定义如下:publicfinalclassSystemextendsObjectSystem类的成员定义如表9-28所示。表9-28System类成员可以看出,System.out和System.err已被包装成了PrintStream对象,而System.in是一个没有被包装过的、未经加工的InputStream流对象。9.4.1从标准输入读取数据
通过以下程序,来了解怎样通过System.in成员从键盘读取数据。
【例9-15】从键盘读取数据。
importjava.io.*;
publicclassReadIn_1
{publicstaticvoidmain(String[]args)
{byteb[]=newbyte[512];
//定义一个字节数组,用来存放键盘数据
intx;
try
{System.out.println("inputdata:");intcount=System.in.read(b);
//从键盘输入数据,直到回车结束,返回读到的字节数
Stringstr=newString(b);
//将字节数组b构造成一个字符串
str=str.substring(0,count-2);
//得到有效数据,去掉“回车换行”两个字符
System.out.println("recievedthedata:");
System.out.println(str);
}
catch(Exceptione){};
}
}
运行结果如图9-35所示。图9-35从键盘读取数据并显示
System.in通过InputStream类的read()方法从键盘按字节读取数据,并将读到的字节值依次存放到字节数组中,直到遇到回车结束。
从键盘读取数据之前,往往要对System.in进行包装,即将System.in构造成Input
StreamReader流。
InputStreamReader流的继承关系如下:InputStreamReader流的构造方法见表9-29,类方法见表9-30。表9-29InputStreamReader类的构造方法表9-30InputStreamReader类的方法
【例9-16】将System.in构造成InputStreamReader流。
importjava.io.*;
publicclassReadIn_2
{publicstaticvoidmain(String[]args)
{intx;
try
{//将键盘输入构造成一个InputStreamReader流InputStreamReaderin=newInputStreamReader(System.in);
System.out.println(“inputdata:”);
while((x=in.read())!=-1)
System.out.print((char)x);
}
catch(Exceptione){};
}
}
注意:在用户输入文本并按回车键后,回显的行才出现。运行结果见图9-36。图9-36从键盘读取数据并回显上例中是逐个读取数据的,通常我们会用readLine()一次一行地读取输入,因此会将System.in包装成BufferedReader来使用。通过对BufferedReader类构造方法的分析,需要事先用InputStreamReader把System.in转换成Reader。
【例9-17】将System.in构造成BufferedReader流。importjava.io.*;
publicclassReadIn_3
{publicstaticvoidmain(String[]args)throwsIOException
{Stringstr1,str2;
InputStreamReadersin=newInputStreamReader(System.in);
//将System.in包装成字符流
BufferedReaderin=newBufferedReader(sin);
//将System.in包装成BufferedReader流
System.out.println(“Inputthefirststring:”);
str1=in.readLine();
//从键盘读取一个字符串System.out.println(“InputtheSecondstring:”);
str2=in.readLine();
if(str1.length()==str2.length())
//字符串长度比较
System.out.println("Theyhavethesamelength!");
else
System.out.println("Theyhavedifferentlength!");
}
}
运行结果见图9-37。图9-37比较输入字符串的长度9.4.2向标准输出写入数据
System.out用于将数据在显示器上打印出来,它是一个PrintStream,即字节输出流。而PrintWriter的构造方法中提供了将OutputStream参数指定的字节流用于字符流处理的功能,因此,只要把System.out转换成PrintWriter对象使用,就可以调用PrintWriter类的方法了。
【例9-18】将System.out构造成PrintWriter流。importjava.io.*;
publicclassWriteOut
{publicstaticvoidmain(String[]args)
{PrintWriterout=newPrintWriter(System.out,true);
out.println(“Welcome:”);
out.println(“将System.out转换成PrintWriter对象的用法!”);
}
}
在创建对象时,使用了两个参数的构造方法,并将第二个参数设为true,以便开启自动清空功能否则就不会输出。运行结果见
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年传染病防治兽药项目规划申请报告
- 2025年建筑安装服务项目提案报告
- 2024-2025学年砚山县数学三上期末质量检测试题含解析
- 2025年果蔬罐头加工项目提案报告
- 2025年低碳小镇项目规划申请报告模板
- 专家邀请函范文锦集六篇
- 质量承诺书模板集合8篇
- 上海装修施工合同
- 学生军训心得体会(集合15篇)
- 电子商务实习自我鉴定9篇
- 白内障手术术后护理和饮食禁忌
- 设立生态农业科技研发公司组建方案
- 《行动研究法》课件
- 云南省昆明市西山区2023-2024学年三年级上学期期末语文试卷
- 办公楼消防安全培训课件
- 肠梗阻病人护理查房课件中医
- 手术室运用PDCA循环提高术毕房间整理完善率
- 2023学校食堂员工劳务合同
- 试生产检查准备表
- 月下独酌(其一)李白
- 《大学物理学》精美课件(全)
评论
0/150
提交评论