黑马程序员----java----io

时间:2021-07-13 10:56:51

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------



IO流(图)

黑马程序员----java----io
黑马程序员----java----io
黑马程序员----java----io

字符流:

Reader与Writer(字符读取与字符写入流) 子类FileReader与FileWriter(专门操作文本的流)

FileWriter对象一创建就必须明确被操作的文件,而且该文件会被创建到指定目录下,如果目录中有同名文件,将被覆盖。 FileWriter("文件路径",true):创建FileWriter对象时,如果在参数内添加true  代表在已有文件后进行续写。 flush();close();
FileReader文本字符读取流, 方法read();  一次读取一个字符,并且会自动往下读。 当读到-1,代表结束。
<span style="font-size:18px;"><span style="font-size:18px;">//将c盘的一个文本文件复制到D盘
import java.io.*;
class CopyText
{
public static void main(String[]args)throws IOException
{
FileReader fr = new FileReader("c:\\DateDemo.java");//创建一个读取流对象并指定读取内容路径
FileWriter fw = new FileWriter("d:\\dateDemo1.java");//创建一个写入流对象,并指定写入的地址路径

char[] ch = new char[1024];//创建char类型数组,并定义大小

int num = 0;//定义一个标记
while((num=fr.read(ch))!=-1)//读取文件,并将读取到的位置用num记录
{
fw.write(new String(ch,0,num));//写出所读到的数据,并将数组转换成String类型,

//件较多时需要刷新
}
fr.close();//关闭读取流
fw.close();//关闭写入流,关闭时会刷新一次

}
}</span></span>
字符流缓冲区:提高读取与写入效率
BufferedWriter: 方法flush():当写入数据时,必须进行刷新才能将文件写入。 方法newLine();换行符。
BufferedReader: 方法reaLine(),一次读取一行,用while循环进行不断读取,当返回空时表示读到文件末尾。
<span style="font-size:18px;"><span style="font-size:18px;">/*
通过缓冲区复制一个.java文件
*/

import java.io.*;
class CopyTextBuf
{
public static void main(String[]args)throws IOException
{
BufferedReader br = new BufferedReader(new FileReader("DateDemo.java"));//创建一个读取缓冲区流 并往里面传入一个读取流对象 并关联一个文件
BufferedWriter bw = new BufferedWriter(new FileWriter("c:\\DateDemo1.java"));//创建一个写入缓冲区流 并往里面传入一个写入流对象 并指定一个写出路径

String line = null;//定义一个读取流标记line 初始化值为空.中转站,连同读取与写出的介质;
while((line=br.readLine())!=null)//读取文件 调用读取缓冲流的readLine方法
{
bw.write(line);//写出数据,调用写出缓冲流的write方法
bw.flush();//刷新
bw.newLine();//换行


}
br.close();//关闭读取缓冲流流
bw.close();//关闭写入缓冲流流
}
}</span></span>


装饰设计模式:
/*
装饰设计模式
当想要对已有的对象进行功能增强时
可以定义类,将已有对象传入,基于已有的功能,并提供加强功能
那么资第一的该类称为装饰类


装饰类通常会通过构造方法接受被装饰的对象,
并基于被装饰对象的功能,提供更强的功能

<span style="font-size:18px;"><span style="font-size:18px;">*/
class Person//被装饰类
{
public void chifan()
{
System.out.println("吃饭");
}
}
class SuperPerson//装饰类
{
private Person p ;
SuperPerson(Person p)
{
this.p=p;
}
public void superChifan()
{
System.out.println("开胃酒");
p.chifan();
System.out.println("甜点");
System.out.println("来一根");
}

}
class PersonDemo
{
public static void main(String[]args)
{
Person p = new Person();

SuperPerson sp = new SuperPerson(p);
sp.superChifan();
}
}</span></span>

LineNumberReader类:(装饰类)
相当于BufferedReader。特有方法: setLineNuber(100):设置行号 getLineNumber():获取行号

字节流: InputStream:字节读取流(子类FileInputStream)   OutputStream:字节读取流(子类OutputStream)
write()方法不需要刷新。
字节流缓冲区:BufferedInputStream,   BufferedOutputStream
<<span style="font-size:18px;">span style="font-size:18px;">class CopyMp31
{
public static void main(String[]args)
{
BufferedInputStream bis = null;
BufferedOutputStream bos = null;

try
{long start = System.currentTimeMillis();//插入一个开始时间标记
bis = new BufferedInputStream(new FileInputStream("1.mp3"));
bos = new BufferedOutputStream(new FileOutputStream("复制11.mp3"));
int len = 0;//定义标记,可以关联读取写入流
while((len=bis.read())!=-1)//只有字符缓冲流的读取返回值类型到结束是null 其他的是-1
{
bos.write(len);//
}
long end = System.currentTimeMillis();//插入一个结束时间标记
System.out.println((end-start)+"毫秒");//打印所耗费的时间
}
catch(IOException e)
{
throw new RuntimeException("复制失败");
}
finally
{
try
{
if(bis!=null)
bis.close();
}
catch(IOException e)
{
throw new RuntimeException("读取流关闭失败");
}
try
{
if(bos!=null)
bos.close();
}
catch(IOException e)
{
throw new RuntimeException("写入流关闭失败");
}
}

}
}</span></span>

转换流:InputStreamReader   OutputStreamWriter
将字节流传入 ,  转换成一个字符流。
<span style="font-size:18px;"><span style="font-size:18px;">import java.io.*;
class InputStreamReaderDemo//字节流转字符流练习
{
public static void main(String[]args)throws IOException
{
//InputStream in = System.in;//定义一个键盘录入,用字节流创建



BufferedReader br = new BufferedReader(new InputStreamReader(System.in));//创建一个字节流转字符流
//键盘录入最常见写法//对象InputStreamReader接受被指定键盘录入的字节输入流对象
//然后这个整体就可以看做一个reader类的对象,用缓冲读取流BufferedReader
//接受这个对象
//OutputStream out = ;//定义一个写入流指向控制台

//OutputStreamWriter osw = ;//创建一个字节流写入转换字符流流写入对象并接收输出到控制台
//并使用缓冲字符流写入对象接收
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

String line = null;//定义一个String变量line 并初始化为空

while((line=br.readLine())!=null)//用line记录 读取缓冲流用readLine方法读取到的键盘录入的数据
{
if(line.equals("over"))//定义一个标记,如果line记录到的数据是over(键盘录入Over)则输入结束
break;

bw.write(line.toUpperCase()+"\r\n");//输出到控制台键盘录入数据的大写形式

bw.flush();//刷新
//bw.newLine();//写入转换流的方法newLine 跨平台换行

}

br.close();//关闭读取缓冲流,在其内部将关闭读取流
bw.close();
}


}</span></span>

IO流操作规律
1,明确源和目的: 源:输入流,InputStream Reader 目的: 输出流: OutputStream  Writer
2,操作的数据是否是纯文本 是:字符流: 不是:字节流:
3,通过设备来进行区分: 原设备:内存,硬盘,键盘。 目的设备:内存,硬盘,控制台。
1)将一个文本文件数据存储到一个文件中。 FileReader   FileWriter
2)将键盘录入的数据保存到一个文件 Reader(InputStreamReader)   FileWriter。
指定编码表存储数据 OutputStreamWriter(OutputStream o ,UTF-8 InputStreamReader(InputStream i ,UTF-8

System类 方法setIn(),改变键盘录入。 方法setOut(),改变控制台输出地址。
异常的日志信息:
<pre name="code" class="java"><span style="font-size:18px;">//log4j  日志信息建立


import java.io.*;
import java.util.*;
import java.text.*;

class ExceptionInfo
{
public static void main(String[]args)throws Exception
{

try
{

int[] arr= new int[2];
System.out.println(arr[3]);
}
catch(Exception e)
{
try
{
Date d = new Date();//创建一个时间对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
<span style="white-space:pre"></span>//定义一个时间格式

PrintStream ps = new PrintStream("11122.txt");
<span style="white-space:pre"></span>//创建一个System.out类的对象ps 并指定输出地址

String s = sdf.format(d);
<span style="white-space:pre"></span>//通过format让时间d 接受一个sdf自定义时间格式
ps.println(s);//将时间打印打PS定义的文件中
System.setOut(ps);//设置System。out标准输出指向ps
<span style="white-space:pre"></span>//System.setOut(new PrintStream(""));
<span style="white-space:pre"></span>//e.printStackTrace(new PrintStream("11122.txt"));
}
catch(IOException ex)
{
throw new RuntimeException("日志文件创建失败");
}
e.printStackTrace(System.out);

}
}
}</span>


File类:用来将文件或文件夹封装成对象。可以作为参数传递给流的构造函数。 separator:与系统有关的目录分隔符。"c:"+separator+"abc"+...   c盘下的abc文件下的。。。  跨平台分隔符。 方法: 1:创建 boolean createNewFile();在指定位置创建文件,如果该文件已经存在,则不创建,返回false。   creareTempFile();  在指定目录下穿件一个新的空文件夹,使用给定的前缀和后缀名。  mkdir();       创建文件夹;  mkdirs();       创建多级文件夹; 2:删除 boolean delete(); void deleteOnExit(); 在文件创建后写上,则在文件退出时将文件删除。 3:判断 boolean canExecute();  是否可以执行。 compareTo(); boolean exists();文件是否存在。 isDirectory();是否是目录。 isFile();是否是文件。 isHidden();是否隐藏。 isAbsolute();是否是绝对路径,(带有盘符)。即使文件不存在也能判断。 4:获取信息 getName(); getPath(); getParent();  文件创建时封装的绝对路径,如果没有,返回null。 getAbsolutePath(); long  lastModified();最后一次修改时间 long  length();文件大小。 FIle[]  listRoots();列出有效的盘符。 String  list(); 路径下所有文件和文件夹名称。    list(FileNameFileter  ff):
<pre name="code" class="java"><span style="font-size:18px;">/*
listFiles():返回File[]
*/
import java.io.*;

class FileDemo2
{
public static void main(String[]args)
{
//File dir = new File("c:\\");

//File[] files = dir.listFiles();
//返回文件名称 listFiles() 可以对返回的文件进行File方法操作

//for(File f: files)
//{
//System.out.println(f.getName()+"++++"+f.length());
//}
listDemo_1();


}
public static void listDemo()
{
File f = new File("c:\\");
String[] names = f.list();
//列出当前目录下所有文件 包括隐藏的文件 并把文件疯转诚意个String类型的数组
for(String s : names)
//调用list方法的file对象必须是封装了一个目录,该目录还必须存在。否则异常
{
System.out.println(s);
}

}
//public static void listDemo()
{

}
public static void listDemo_1()
{
File dir = new File("d:\\java1.1\\date24");//创建一个文件,文件夹指向一个路径
File[] arr = dir.listFiles(new FilenameFilter()
//用String类型的数组存储file中list的方法列出来的文件

//在list方法中传入一个匿名内部类,FilenameFilter接口,并覆盖其方法accept

//返回.exe文件
{
public boolean accept(File dir,String name)
//覆盖接口FilenameFilter中的方法 并传入要遍历的文件,和需要去除的文件名
{

//System.out.println(dir+"......"+name);
/*
if(name.endsWith(".txt"))
{
return ture;
}
*/

return name.endsWith(".java");//取出相对的文件名条件

}
});
System.out.println(arr.length);//打印数组的长度
for(File name : arr)//遍历数组,打印出用上述方法得到的文件名
{
System.out.println(name);
}
}
public static void listRootsDemo()
{
File[] files = File.listRoots();//列出机器有效的盘符,并用File数组进行封装
for(File f : files)//罗列数组里的文件
{
System.out.println(f);
}

}
}</span>



递归:自己调用自己的方法
<span style="font-size:18px;">class FileDemo3
{
public static void main(String[]args)
{
File dir = new File("d:\\java1.1");//创建一个文件对象 并指定一个目录
showDir(dir,0);//
//int n =getSum(100);
//System.out.println(n);
}
public static int getSum(int n )//递归:自己调用自身方法,然后逐层返回
{
if(n==1)
return 1;
return n +getSum(n-1);//递归

}

public static void toBin(int num)//递归方法 十进制到二进制转换
{
while(num>0)
{
toBin(num/2);
System.out.println(num%2);
//num = num/2;
}
}
public static String getLevel(int level)//定义一个返回值为String类型的方法 并往里传入一个int类型的数据
//用于记录文件的层级
{
StringBuilder sb = new StringBuilder();//创建一个可变长度的StringBuilder集合


for(int x=0; x<level; x++)//循环 当x<level
{
sb.append(" ");
}
return sb.toString();//sb的初始化值为空,所有第一次返回一个空参数
}

public static void showDir(File dir,int level)
{

//System.out.println(dir+"目录**************************************");
System.out.println(getLevel(level)+dir.getName());//第一次打印java1.1
//第二次打印名字时level为1 目录前加双空格

level++;//level自增
File[] files = dir.listFiles();//在这里已经将一级目录中所有的参数列出
System.out.println()
for(int x=0; x<files.length;x++)
{
if(files[x].isFile())
System.out.println(getLevel(level)+files[x].getName());//第三次打印文件时level是2 前面打印4个空格
else
showDir(files[x],level);//递归,第二次调用showDir方法时返回的level是1


}
}
}</span>

删除一个带内容的目录:


<span style="font-size:18px;">/*
删除一个带文件的文件夹
删除原理
在windows中 删除目录从里完外删

递归
*/

import java.io.*;
class RemoveDir
{
public static void main(String[]args)
{
File dir = new File("c:\\haha");
removeDir(dir);
}
public static void removeDir(File dir)
{
File[] files =dir.listFiles();//隐藏的也会遍历到
for(File name : files)//遍历的时候应该排除隐藏的文件
{
if(name.isFile())
name.delete();//删除的时候会找不到隐藏的文件
else
removeDir(name);
}
dir.delete();
}
}</span>

创建一个免费试用程序代码
<span style="font-size:18px;">import java.io.*;
import java.util.*;

class RunCount
{
public static void main(String[]args)throws IOException
{


Properties prop = new Properties();//创建集合

File file = new File("count.ini");//创建文件并封装成对象

if(!file.exists())//判断文件是否存在
file.createNewFile();//不存在的话创建

FileInputStream fis = new FileInputStream(file);//创建读取流并关联file

prop.load(fis);//将流中的数据存储到prop中

int count = 0;//定义标记
String value = prop.getProperty("time");//获取键对应的值,

if(value!=null)//当键不存在的时候
{
count = Integer.parseInt(value);//用count记录使用次数.
if(count>=5)//判断count
{
System.out.println("免费次数已到,请充值");//提示并退出程序
return;
}
}
count++;//count自增

prop.setProperty("time",count+"");//将键对值从新存入集合

FileOutputStream fos = new FileOutputStream(file);//并通过写出流关联文件

prop.store(fos,"");//将集合中的内容通过流以键值对的形式写到具体文件中.

fos.close();
fis.close();

}
}</span>


打印流:PrintStream(字节打印流)与PrintWriter(字符打印流)
PrintStream:构造函数可以接收的参数类型:file对象,字符串路径,字节输出流。
PrintWriter:构造函数可以接收的参数类型:file对象,字符串路径,字节输出流,字符输出流。

序列流:SequenceInputStream 构造函数接收多个流进入,从第一个流开始读取,到最后一个流结束,去读取数据。
<span style="font-size:18px;">/*
SequenceInputStream:将多个个流连接
*/
import java.io.*;
import java.util.*;
import java.io.SequenceInputStream;

class SequenceInputStream1
{
public static void main(String[]args)throws IOException
{
Vector<FileInputStream> v = new Vector<FileInputStream>();//创建一个Vector集合
v.add(new FileInputStream("c:\\1.txt"));//添加流对象元素并关联文件
v.add(new FileInputStream("c:\\2.txt"));
v.add(new FileInputStream("c:\\3.txt"));
System.out.println(v.size());//打印集合长度


//Enumeration<FileInputStream> en = v.elements();

SequenceInputStream sis = new SequenceInputStream(v.elements());//创建多个流连接对象
//并传入由v封装的多个流,用Vector的方法elements得到Enumeration枚举的对象

FileOutputStream fos = new FileOutputStream("c:\\4.txt");//创建一个写入流,并关联一个输出文件

byte[] arr = new byte[1024];//创建一个数组存储数据

int num = 0;//定义一个标记

while((num=sis.read(arr))!=-1)
{
fos.write(arr,0,num);//写出数据


}
fos.close();
sis.close();



}
}</span>

split流的切割
<span style="font-size:18px;">/*
split切割文件
*/
import java.io.*;
import java.util.*;
import java.io.SequenceInputStream;


class SplitDemo
{
public static void main(String[]args)throws IOException
{
merge();
}

public static void splitFile()throws IOException
{
FileInputStream fi = new FileInputStream("11.mp3");//创建一个读取流 关联一个文件

FileOutputStream fos = null;//创建一个写入流引用

byte[] arr = new byte[1024*1024];//创建一个存储数组

int count = 1;//标记一个
int len = 0;//标记
while((len=fi.read(arr))!=-1)//读取
{

fos = new FileOutputStream((count++)+".part");//创建写出流
fos.write(arr,0,len);//写出去
fos.close();//关闭流
}
fi.close();
}
public static void merge()throws IOException
{
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();//创建一个存储读取流的集合
for(int x = 1; x<=4; x++)
{
al.add(new FileInputStream(x+".part"));

}
final Iterator<FileInputStream> it = al.iterator();//迭代取出al中的片段

Enumeration <FileInputStream> en = new Enumeration<FileInputStream>()//匿名内部类访问的局部成员要用final修饰
{
public boolean hasMoreElements()
{
return it.hasNext();
}
public FileInputStream nextElement()
{
return it.next();
}
};
SequenceInputStream sis = new SequenceInputStream(en);//创建一个大流接受片段流

FileOutputStream fos = new FileOutputStream("0.mp3");//创建输出流
byte[] buf = new byte[1024];
int num = 0;
while((num=sis.read(buf))!=-1)
{
fos.write(buf,0,num);//写出数剧
}
fos.close();
sis.close();
}
}</span>

ObjectInputStream与ObjectInputStream(直接操作对象的流)

被操作的对象需要实现Serializable(标记接口)。
ObjectInputStream可以操作基本数据类型 

每一个类在序列化的时候都会存在一个UID,根据类的内容计算出来的。当被序列化就是对象的持久化,将对象存储到硬盘上。 当一个类的内容被改变时,这个类的UID也会被改变,这样就不能再用ObjectInputStream读取到该类中的数据。可以用public static  final  long serialVersionUID = 42L;来设置一个固定的UID。
transient关键字, 用这个关键字修饰的变量不能被序列化。
<span style="font-size:18px;">public class ObjectStreamDemo {

public static void main(String[] args)throws IOException, ClassNotFoundException {
readobj();

}

public static void readobj() throws FileNotFoundException, IOException, ClassNotFoundException
{

ObjectInputStream ois =
new ObjectInputStream(new FileInputStream("obj.txt"));//将文件读取并打印在控制台上。

Person p = (Person)ois.readObject();//一次读取一个对象

System.out.println(p);

ois.close();


}
public static void writeObj() throws IOException {//将对象持久化存储到文件中


ObjectOutputStream oos =
new ObjectOutputStream(new FileOutputStream("obj.txt"));


oos.writeObject(new Person("lisi",30));

oos.close();
}
}</span>

RandomAccessFile类,直接继承与Object
随机访问文件,自身具备读写的方法。通过skipBytes(int x),seek(int x)来达到随机访问 它内部封装了一个byte数组,通过指针对数组的元素进行操作。可以通过getFilePointer获取指针位置。(内部封装了字节流)。。。。。。局限性:该类只能操作文件。  并且有mode模式:r  读,rw,读写。如果是r则不能写数据。    如果模式为只读,不会创建文件,回去读取一个已存在的文件,如果该文件不存在,则会出现异常。如果模式为rw,需要操作的文件不存在,则创建,存在则不会覆盖。
<span style="font-size:18px;">import java.io.IOException;
import java.io.RandomAccessFile;

public class RandomAccessFileDemo {

public static void main(String[] args) throws IOException {
//readFile();
writeFile2();
}

public static void readFile() throws IOException
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","r");
//调整对象中的指针
//raf.seek(8*1);//设置角标位置。
raf.skipBytes(8);//跳过8个字节,不能往回跳




byte[]buf = new byte[4];
raf.read(buf);
String name = new String(buf);
int age = raf.readInt();
System.out.println(name);
System.out.println(age);
raf.close();
}


public static void writeFile() throws IOException
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");//创建读写的RandomAccessFile对象。

raf.write("李四".getBytes());
raf.writeInt(88);
raf.write("王五".getBytes());
raf.writeInt(99);

raf.close();


}
public static void writeFile2() throws IOException
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");

raf.seek(8*3);//指定位置读写,如果设置的角标有数据,则覆盖。,实现数据的分段存入。
raf.write("周七".getBytes());
raf.writeInt(88);
raf.close();
}

}</span>









管道流:PipedInputStream和PipedOutputStream,输入输出可以直接进行谅解,通过结合线程使用。(设计到多线程) 构造函数相互作为参数传入。
<span style="font-size:18px;">import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

public class PipedStreamDemo {

public static void main(String[] args) throws IOException {
PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream();

in.connect(out);

Read r = new Read(in);
Write w = new Write(out);

new Thread(r).start();//1
new Thread(w).start();//2


}

}


class Read implements Runnable
{
private PipedInputStream in;
Read(PipedInputStream in)
{
this.in=in;
}
public void run()
{
try
{
byte[] buf = new byte[1024];

int len = in.read(buf);//没有数据等待,下面写数据到这里来

String s = new String(buf,0,len);//

System.out.println(s);//写出数据

in.close ();
}
catch(IOException e)
{
throw new RuntimeException("管道流读取失败");
}

}

}
class Write implements Runnable
{
private PipedOutputStream out;
Write(PipedOutputStream out)
{
this.out = out;
}
public void run()
{
try
{
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
out.write("管道来了".getBytes());//写出数据 ,写到上面的读取流中

out.close ();
}
catch(IOException e)
{
throw new RuntimeException("管道流输出失败");
}
}
}</span>

DataInputStream与DateOuputStream(操作基本数据类型)

<span style="font-size:18px;">import java.io.DataOutputStream;

import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;


public class DateStreamDemo {
public static void main(String[] args) throws IOException {
writeDate();
read();
writeUTFDemo();
readUTFDemo();
}

public static void readUTFDemo() throws IOException//读UTF
{
DataInputStream dis = new DataInputStream(new FileInputStream("UTFDATE.txt"));
String s = dis.readUTF();
System.out.println(s);
dis.close();
}
public static void writeUTFDemo() throws IOException//写UTF编码
{
DataOutputStream dos = new DataOutputStream(new FileOutputStream("UTFDATE.txt"));

dos.writeUTF("你好");

dos.close();
}
public static void writeDate() throws IOException {//写基本数据
DataOutputStream dos = new DataOutputStream(new FileOutputStream("date.txt"));

dos.writeInt(234);
dos.writeBoolean(true);
dos.writeDouble(3.14);

}
public static void read() throws IOException//读基本数据
{
DataInputStream dis = new DataInputStream(new FileInputStream("date.txt"));

int num = dis.readInt();
boolean b = dis.readBoolean();
double d = dis.readDouble();

System.out.println(num);
System.out.println(b);
System.out.println(d);
}

}</span>



ByteArrayInputStream与ByteArrayInputStream(操作字节数组)内部都有缓冲。 ByteArrayInputStream:没有调用过底层资源,不会产生IO异常。 ByteArrayInputStream:没有调用过底层资源,不会产生IO异常。

CharArrayReader与CharArrayWrite(操作字符数组)
StringReader与StringWriter(操作字符串)





IO异常的处理方式:




<span style="font-weight: normal;">class FileWriterDemo2
{
public static void main(String[]args)
{
FileWriter fw =null;//建立外部引用
try{
fw = new FileWriter("文件路径");
fw.Writer("数据");
}
catch(IOException e)
{
System.out.println(e.toString());
}
finally
{

try{
if(fw!=null)//如果不判断,当fw不存在,就会发生关闭失败异常。
fw.close();
}
catch (IOException e)
{
System.out.println(e.toString());
}

}
}
}</span>






















































黑马程序员----java----io
黑马程序员----java----io