第8章 IO补充案例.docx
《第8章 IO补充案例.docx》由会员分享,可在线阅读,更多相关《第8章 IO补充案例.docx(55页珍藏版)》请在冰豆网上搜索。
第8章IO补充案例
第八章补充案例
案例8-1FileInputStream读取文件数据
一、案例描述
1、考核知识点
名称:
字节流读写文件--读取文件
2、练习目标
Ø掌握如何使用FileInputStream字节流读取文件中数据
3、需求分析
在操作文件时,最常见的就是从文件中读取数据并将数据写入文件,即文件的读写。
针对文件的读操作,JDK专门提供了FileInputStream类。
为了让初学者掌握FileInputStream字节流的使用,在案例中将针对读取并打印指定文件中的数据进行演示。
4、设计思路(实现原理)
1)
2)在同一目录下创建Example01.java文件,编写Example01类。
3)在main()方法中,通过FileInputStream(Stringname)构造方法创建文件输入字节流对象,并指定待读取文件fis.txt的路径。
4)在while循环条件中使用read()方法每次读取一个字节,同时在循环体中打印每次读取的数据,当read()方法返回值为-1时表示读取到文件结尾,循环结束。
5)使用close()方法,关闭流资源。
二、案例实现
importjava.io.FileInputStream;
importjava.io.IOException;
publicclassExample01{
publicstaticvoidmain(String[]args)throwsIOException{
//创建字节输入流对象
FileInputStreamfis=newFileInputStream("fis.txt");
//读取所有字节
intby=0;
while((by=fis.read())!
=-1){
System.out.print((char)by);
}
//关闭字节输入流
fis.close();
}
}
运行结果如图8-1所示。
图8-1运行结果
从运行结果可以看出,使用FileInputStream类成功地读取出fis.txt文件中的数据。
三、案例总结
1、通过FileInputStream(Stringname)构造方法创建FileInputStream对象时,传入的待读取文件的路径,可以是相对路径也可以是绝对路径。
2、在读取文件数据时,必须保证文件是存在并且可读的,否则会抛出文件找不到的异常FileNotFoundException。
3、FileInputStream类有三个重载的read()方法,如果方法返回值为-1,均表示已读取到了文件的结尾。
4、为了使流对象所占用的系统资源得到释放,请记住调用FileInputStream类close()方法关闭字节流。
5、思考一下:
修改Example01类,如何实现只读取文件的单个字节?
代码如下:
importjava.io.FileInputStream;
importjava.io.IOException;
/*
*读取单个字节
*/
publicclassExample01{
publicstaticvoidmain(String[]args)throwsIOException{
//创建字节输入流对象
FileInputStreamfis=newFileInputStream("fis.txt");
//读取单个字节
inti=fis.read();
System.out.println(i);
//关闭字节输入流
fis.close();
}
}
案例8-2FileOutputStream写入数据
一、案例描述
1、考核知识点
名称:
字节流读写文件--写入文件
2、练习目标
Ø掌握如何使用FileOutputStream字节流向文件写入数据
3、需求分析
与FileInputStream对应的是FileOutputStream,它是操作文件的字节输出流,专门用于把数据写入文件。
为了让初学者掌握FileOutputStream字节流的使用,在案例中将通过演示向文本文件写入一段文字来学习。
4、设计思路(实现原理)
1)编写Example02类。
2)在main()方法中,通过FileOutputStream(Stringname)构造方法创建文件输出字节流对象,并指定写入的文件路径。
3)定义一段字符串,并将它转换成byte数组,然后通过write(byte[]b)方法,将byte数组写入到文件输出流中。
4)使用FileOutputStream类的close()方法,关闭流资源。
二、案例实现
importjava.io.FileOutputStream;
importjava.io.IOException;
publicclassExample02{
publicstaticvoidmain(String[]args)throwsIOException{
//创建字节输出流对象
FileOutputStreamfos=newFileOutputStream("fos.txt");
//用字符串转换字节数组
byte[]b="欢迎学习IO流".getBytes();
//将数组中数据写入文件
fos.write(b);
//关闭输出流
fos.close();
}
}
程序运行后,会在当前目录下生成一个新的文本文件fos.txt,文件内容如图8-2所示:
图8-2fos.txt
从运行结果可以看出,使用FileOutputStream类成功把数据写入文件。
三、案例总结
1、与FileInputStream读取的文件必须存在不同,FileOutputStream写入数据的文件不必是已存在的,因为该文件会被自动创建。
2、FileOutputStream类有三个重载的write()方法,可以分别向文件中一次写入单个字符、字符数组以及数组的部分数据。
3、思考一下:
我们在使用案例中的方式,多次向fos.txt文件中写入不同数据时,发现文件中原有内容被新数据替代了。
请问如果希望在原有文件内容之后追加新内容,如何修改Example02类?
代码如下:
importjava.io.FileOutputStream;
importjava.io.IOException;
publicclassExample02{
publicstaticvoidmain(String[]args)throwsIOException{
//创建字节输出流对象
FileOutputStreamfos=newFileOutputStream("fos.txt",true);
//用字符串转换字节数组
byte[]b=",真的很好玩".getBytes();
//将数组内容写入文件
fos.write(b);
//关闭输出流
fos.close();
}
}
程序运行后,再次打开fos.txt,文件内容如图8-3所示:
图8-3fos.txt
以上代码中使用了FileOutputStream的另一个构造方法FileOutputStream(String fileName,boolean append)来创建文件输出流对象,当设置append参数值为true时表示追加内容,从上图可以看出新内容成功追加到原有内容以后。
案例8-3自定义缓冲区拷贝大文件
一、案例描述
1、考核知识点
名称:
字节流的缓冲区
2、练习目标
Ø掌握如何自定义缓冲区
Ø掌握如何使用自定义缓冲区读、写文件
Ø了解自定义缓冲区读写的优点
3、需求分析
操作文件时一个个字节的读写,效率非常低,为了提高效率可以自定义一个字节数组作为缓冲区。
为了让初学者掌握如何使用自定义缓冲区读写文件,案例中将演示使用字节流的自定义缓冲区拷贝“IO流.avi”文件到其它目录来学习。
4、设计思路(实现原理)
1)在当前目录下创建source和target文件夹,并在source文件夹中存放一个“IO流.avi”文件。
2)编写Example03类。
3)在main()方法中,分别创建文件字符输出流和文件字符输入流对象,并指定文件拷贝的源及目标路径。
4)自定义一个1024长度的字节数组作为缓冲区,然后通过输入流将源文件数据读取到缓冲区中,输出流再将缓冲区中数据写入到目标文件中,循环往复直到文件拷贝结束,并计算拷贝文件总耗时。
5)使用close()方法,关闭流资源。
二、案例实现
importjava.io.*;
publicclassExample03{
publicstaticvoidmain(String[]args){
FileInputStreamfis=null;
FileOutputStreamfos=null;
try{
//创建文件字符输出流和文件字符输入流对象
fis=newFileInputStream("source\\IO流.avi");
fos=newFileOutputStream("target\\IO流.avi");
//创建字节数组,用于缓存读取的字节
byte[]bys=newbyte[1024];
intlen=0;
//读取到文件结束时,返回-1
while((len=fis.read(bys))!
=-1){
//将缓冲区中的数据写入文件
fos.write(bys,0,len);
}
}catch(IOExceptione){
e.printStackTrace();
}finally{
try{
//关闭流资源
fis.close();
}catch(IOExceptione){
e.printStackTrace();
}
try{
//关闭流资源
fos.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
}
程序运行结束后,打开target文件夹,发现source文件夹中的“IO流.avi”文件被成功拷贝到了target文件夹,如图8-4所示。
图8-4拷贝结果
程序运行结束后,会在命令行窗口输出拷贝文件所消耗的时间,如图8-5所示:
图8-5运行结果
从运行结果可以看出,使用自定义缓冲区拷贝大文件成功,而且耗时较短。
三、案例总结
1、由于计算机性能等各方面原因,会导致每次拷贝文件所消耗的时间未必相同。
2、在指定文件路径时使用了“\\”,这是因为在Windows目录路径基础上使用了转义符“\”。
3、为了保证IO流的close()方法必须执行,通常将关闭流的操作写在finally代码块中。
4、思考一下:
使用自定义缓冲区拷贝文件时效率高耗时短,请修改Example03类,在不使用缓冲区的情况下拷贝文件,打印所消耗的时间,并与使用缓冲区所耗时间比较。
代码如下:
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.IOException;
publicclassExample03{
publicstaticvoidmain(String[]args){
FileInputStreamfis=null;
FileOutputStreamfos=null;
try{
//创建文件字符输出流和文件字符输入流对象
fis=newFileInputStream("source\\IO流.avi");
fos=newFileOutputStream("target\\IO流.avi");
//创建字节数组,用于缓存读取的字节
intlen=0;
//读取到文件结束时,返回-1
while((len=fis.read())!
=-1){
//将缓冲区中的数据写入文件
fos.write(len);
}
}catch(IOExceptione){
e.printStackTrace();
}finally{
try{
//关闭流资源
fis.close();
}catch(IOExceptione){
e.printStackTrace();
}
try{
//关闭流资源
fos.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
}
案例8-4装饰设计模式的应用
一、案例描述
1、考核知识点
名称:
装饰设计模式
2、练习目标
Ø了解什么是装饰设计模式
Ø掌握装饰设计模式的应用
3、需求分析
装饰设计模式是通过包装一个类,动态地增强它的功能的一个设计模式,为了让初学者掌握装饰设计模式的应用,在案例将通过使用NewPerson类装饰Person类,完成为Person类增强“吃饭”功能来学习。
4、设计思路(实现原理)
1)编写Person类,定义eat()方法,表示“吃饭”功能
2)编写NewPerson类,定义一个有参构造方法,通过构造方法可以将Person对象传入该类,在NewPerson类定义newEat()方法,该方法对“吃饭”功能进行了扩展和增强。
3)编写Example04测试类,在main()方法中,分别通过Person和NewPerson对象调用装饰前后的吃饭功能。
二、案例实现
/**
*被装饰类
*/
classPerson{
//吃饭功能
publicvoideat(){
System.out.println("正在吃饭");
}
}
/**
*装饰类
*/
classNewPerson{
//装饰类中拥有被装饰类的引用
privatePersonp;
//构造方法传入被装饰类的对象
publicNewPerson(Personp){
this.p=p;
}
//通过装饰类增强吃饭功能
publicvoidnewEat(){
System.out.println("饭前小酒");
p.eat();
System.out.println("抽一根烟");
System.out.println("饭后甜点");
}
}
/**
*测试类Example04
*/
publicclassExample04{
publicstaticvoidmain(String[]args){
System.out.println("----装饰前----");
Personp=newPerson();
p.eat();
System.out.println("----装饰后----");
//使用NewPerson类来装修Person类
NewPersonnp=newNewPerson(newPerson());
np.newEat();
}
}
运行结果如图8-6所示。
图8-6运行结果
从运行结果可以看出,通过装饰设计模式成功增强了“吃饭”功能,达到预期效果。
三、案例总结
1、装饰设计模式具有以下特点:
(1)装饰对象包含一个被装饰对象的引用。
(2)装饰对象接受所有来自客户端的请求,再把这些请求转发给被装饰的对象。
(3)装饰对象可以给被装饰对象增强功能。
(4)一般情况下装饰和被装饰对象会具有相同的接口。
2、思考一下:
装饰设计模式可以通过一个类增强另一个类的功能,而使用继承子类也可以对父类中的功能进行增强,针对增加功能这种情况请问使用装饰设计模式和继承有什么区别。
案例8-5字节缓冲流拷贝大文件
一、案例描述
1、考核知识点
名称:
字节缓冲流
2、练习目标
Ø了解什么是字节缓冲流
Ø了解字节缓冲流的优点
Ø掌握如何使用字节缓冲流拷贝文件
3、需求分析
我们学习过使用自定义缓冲区高效读写文件,其实Java自身也提供了两个带缓冲的字节流,分别是BufferedInputStream和BufferdOutputStream。
为了熟悉这两个字节缓冲流的使用,案例中将通过使用字节缓冲流一次读写一个字节数组的方式拷贝文件来学习。
4、设计思路(实现原理)
1)在source目录下存放“IO流.avi”文件,并确保target目录下没有上次拷贝遗留的文件。
2)编写Example05类。
在main()方法中,分别创建缓冲字节输出流和缓冲字节输入流对象,并指定拷贝文件的源及目标路径。
3)定义一个字节数组作为缓冲区,缓冲输入流将源文件数据读取到缓冲区中,然后缓冲输出流将缓冲区中数据写入到目标文件中,循环往复直到文件拷贝结束,并计算拷贝文件总耗时。
4)使用close()方法,关闭流资源。
二、案例实现
importjava.io.BufferedInputStream;
importjava.io.BufferedOutputStream;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.IOException;
/**
*字节缓冲流一次读写一个字节数组
*/
publicclassExample05{
publicstaticvoidmain(String[]args){
BufferedInputStreambis=null;
BufferedOutputStreambos=null;
try{
bis=newBufferedInputStream(
newFileInputStream("source\\IO流.avi"));
bos=newBufferedOutputStream(newFileOutputStream(
"target\\IO流.avi"));
byte[]b=newbyte[1024];
intlen=0;
while((len=bis.read(b))!
=-1){
bos.write(b,0,len);
}
}catch(IOExceptione){
e.printStackTrace();
}finally{
if(bis!
=null){
try{
bis.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
if(bos!
=null){
try{
bos.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
}
}
}
程序运行结束后,打开target文件夹,发现source文件夹中的“IO流.avi”文件被成功拷贝到了target文件夹,如图8-7所示。
图8-7拷贝结果
程序运行结束后,会在命令行窗口打印拷贝文件所消耗的时间,如图8-8所示。
图8-8运行结果
从运行结果可以看出,使用字节缓冲流一次读写一个字节数组的方式拷贝文件成功,并且速度较快。
三、案例总结
1、字节缓冲流在初次拷贝文件时耗时较长,之后耗时较少。
2、思考一下:
多次拷贝一个较大的文件,比较教材中的字节缓冲流一次读写一个字节方式,与案例8-3中自定义缓冲区方式,以及本案例中字节缓冲流一次读写一个字节数组方式三者之间,谁的拷贝耗时最多?
比较后发现教材中的方式最慢。
案例8-6FileReader读取字符数据
一、案例描述
1、考核知识点
名称:
字符流读取文件
2、练习目标
Ø了解什么是FileReader字符流及其特点
Ø了解FileReader和FileInputStream的区别
Ø掌握如何使用FileReader字符流读取文本文件数据
3、需求分析
如果想从文件中直接读取字符可以使用字符输入流FileReader,通过此流可以从关联的文件中读取一个或一组字符。
为了让初学者掌握FileReader字符流的使用,在案例中将针对一次读取一个字符的方式读取文本文件来学习。
4、设计思路(实现原理)
1)
2)在同一目录下创建Example06.java文件,编写Example06类。
3)在main()方法中,通过FileReader(StringfileName)构造方法创建字符输入流对象,并指定待读取文件fr.txt的路径。
4)使用read()方法循环读取并输出数据,当方法返回值为-1时表示读取到文件结尾,循环结束。
5)使用close()方法,关闭流资源。
二、案例实现
importjava.io.FileReader;
importjava.io.IOException;
publicclassExample06{
publicstaticvoidmain(String[]args)throwsIOException{
//创建字符输入流对象
FileReaderfr=newFileReader("fr.txt");
intby=0;
//判断是否是文件的结尾
while((by=fr.read())!
=-1){
//不是就打印出读取的字符
System.out.print((char)by);
}
//关闭字节输入流
fr.close();
}
}
运行结果如图8-9所示。
图8-9运行结果
从运行结果可以看出,使用FileReader成功地读取出文本文件数据。
三、案例总结
FileReader和FileInputStream有非常多相似之处,但是FileReader每次读取的单位是一个字符,而FileInputStream每次读取的单位是一个字节。
案例8-7FileWriter写入字符数据