<span style="font-size:18px;"><span style="font-size:18px;">/*我们来看一下字符流的特点既然IO流是用于操作数据的,我们先来看比较直观的操作,那就是对文件的操作!下面以演示文件为主来操作基本需求:在硬盘上,创建一个文件并写入一些基本的文字数据最终在API中帮组文档中,找到了一个用于操作文件的Writer子类对象:FileWriter,其中后缀名是父类名称,前缀名是该流的对象功能,File就是文件*/import java.io.*;class WriterDemo1 {public static void main(String[] args) throws IOException{//1.创建输入文件io流的时候,会抛出IO异常//初始化时,文件就必须是先存在的,这样才能进行操作!//【注意】/*创建一个FileWriter对象,该对象一旦被初始化就必须要明确被操作的文件而且该文件会被创建到指定的目录下,如果该目录下已经有同名的文件,就会进行覆盖其实该步骤就是涉及在明确数据要存放的目的地!*/FileWriter fw=new FileWriter("crystal.txt"); //这里的crystal.txt文件和WriterDemo1.class文件同目录//2.调用write方法,将字符串写入到流中去fw.write("hello someone,you are good!");//3.必须刷新对象中的缓冲流,才能将流中的内容写到文件中去……//不刷新是不可能写入的,还会存在流中的缓冲中!fw.flush();//4.刷新之后,才能继续进行写入操作!fw.write("today is very nice!");/*5.对于流不用了,要释放内存中的流资源!也就是关闭【注意】但是在关闭之前,该方法会自动去调用一次flush方法将数据写入到文件中去,最后才关闭!【重点】flush和close的区别:flush刷新之后,流可以直接使用,但是close则是,先刷新,再关闭,流就已经释放了,不能继续使用了!*/fw.close();}}</span></span>
<span style="font-size:18px;"><span style="font-size:18px;">/*
IO异常的专业处理方式:
【记住】最基本的流创建,写入,关闭都是会产生IOException的,所以必须处理
*/
import java.io.*;
class WriterDemoIOException2
{
public static void main(String[] args)
{
//定义在try外,主要是为了让finally也能执行到
FileWriter fw=null;
try
{
fw=new FileWriter("d:\\crystal.txt");
//其中第一个\是转义字符,这样系统才知道d:\crystal.txt文件的位置
fw.write("ni hao !");
}
catch (IOException e)
{
sop(e.toString()); //如果系统没有d盘,就会抛出系统找不到指定的路径FileNotFoundException。
}
finally
{
//【注意】这里必须单独try一个
//这里是必须执行的,但是fw内存中认识不到……
//【解决方案:】在try外建立对象的引用,在try内建立初始化就OK了
//所以在try外fw=null;
try
{
//这里如果对象fw没有创建成功,那样的话为null,这时候就会抛出NullPointerException(空指针异常)
//所以这里必须进行判断:
if (fw!=null)
fw.close();
//同理:如果存在多个流,那样的话都必须依次关闭才行!
}
catch (IOException e)
{
sop(e.toString());
}
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}</span></span>
<span style="font-size:18px;"><span style="font-size:18px;">/*
演示对已有文件的续写:
【重点】,如果用原来直接指定文件位置的方法续写的话,该文件存在就会被覆盖掉了
所以这里用FileWriter fw=new FileWriter("文件的位置",ture);
true:代表的是在此文件的基础上继续在文件的末尾数续写内容!
*/
import java.io.*;
class FileWriterDemo3
{
public static void main(String[] args)
{
FileWriter fw=null;
try
{
//用了这种构造函数的方式,如果文件存在就不会覆盖原来的文件,如果没有,他会自动建立
fw=new FileWriter("crystal.txt",true);
/*
在此文件中写入内容
【注意】\r ,\n是windows系统中能是唯一能被识别的两种换行方式!windows中有些软件能
识别\r,有些能识别\n,所以最好两种都写上,在txt中,就只识别\r
*/
fw.write("hello anybody! \r\nhello boys and girls !");
}
catch (IOException e)
{
sop(e.toString());
}
finally
{
try
{
if (fw!=null)
{
fw.close();
}
}
catch (IOException e)
{
sop(e.toString());
}
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}</span></span>
<span style="font-size:18px;"><span style="font-size:18px;">/*
那么怎样在有内容的文件中,读取出其内容呢?
下面我们就演示从File中读取出文件的操作方式
【读取方式一】读取单个的字符
这种方式是读一个查看一个,读一个查看一个
int read();当返回值为-1时,就是已经读取完毕了!
*/
import java.io.*;
class ReaderDemo4
{
public static void main(String[] args) throws IOException
{
//创建一个文件的读取流对象,和指定名称的文件相关联
//要保证该文件是已经存在的,如果不存在,就会发生异常:FileNotFoundException
FileReader fr=new FileReader("crystal.txt");
/*
//调用读取流对象的方法(读取单个字符的方法),read()方法会自动往下读取数据
int a1=fr.read();
sop((char)a1);
int a2=fr.read();
sop((char)a2);
int a3=fr.read();
sop((char)a3);
int a4=fr.read();
sop((char)a4);
……………………………………
int a……=fr.read();
sop(a……); 当读到最后一个之后,文件中没有内容了,这时候就会返回一个-1
……………………………………
【所以】read方法会自动读取下一个内容,如何确定文件是否到达结尾,就用read()==-1进行判断就行
while (true)
{
int ch=fr.read();
if (ch==-1)
{
break;
}
sop((char)ch);
}
*/
//简化上面的代码:
int a=0;
while ((a=fr.read())!=-1)
{
sop((char)a);
}
fr.close(); //读取操作完之后记得关闭
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
</span></span>
<span style="font-size:18px;"><span style="font-size:18px;">/*
读取内容的方式二:
思想:读一个存一个在数组中,读一个又存一个在组数中,知道读完为止,直接打印数组中的值即可……
*/
import java.io.*;
class FileRead42
{
public static void main(String[] args) throws IOException
{
FileReader fr=new FileReader("crystal.txt");
char[] ch=new char[1024];//1024长度相当于能存储2kb的文件大小了
//这里的num是指读取的次数,因为数据长度为3,所以一次只能读取三个,
//如果再用read方法,而且会重新再取出,覆盖掉原来数组中的元素
//我在记事本中的内容是:你iha236
/*
int num=fr.read(ch);//第一次,三个
sop("num="+num+" "+new String(ch)); //num=3 你ih
int num1=fr.read(ch);
sop("num="+num1+" "+new String(ch)); //num=3 a23
int num2=fr.read(ch);
sop("num="+num2+" "+new String(ch)); //num=1 623
int num3=fr.read(ch);
sop("num="+num3+" "+new String(ch)); //num=-1 623
*/
//因为已经读取到内容的最后了,还要继续读的话,他就会返回-1,代表没有数据可以读了,
//已经到末尾了!
//上面这种方式编写很复杂,我们直接简化,用循环就搞定!
int numbers=0;
while ((numbers=fr.read(ch))!=-1)
{
sop("numbers="+numbers+" "+new String(ch,0,numbers));
}
//这里用到了把数组内容转化为字符串的形式……
//打印效果是一样的,这时我们就把字符数组的长度定义大一点,为1024
//这时候上面的打印结果就是:numbers=7 你iha236
fr.close();
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
</span></span>
<span style="font-size:18px;"><span style="font-size:18px;">/*
练习:读取出.java的文件,显示在屏幕上
这里就以读取FileRead43.java文件内容为例
*/
/*import java.io.*;
class FileRead43
{
public static void main(String[] args) throws IOException
{
FileReader fr=new FileReader("FileRead43.java");
char[] ch=new char[1024];
int num=0;
while ((num=fr.read(ch))!=-1)
{
sop(new String(ch,0,num));
}
fr.close();
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}*/
//下面这种方式是标准的异常处理,实际开发中都是这样写,在main方法上直接抛出所有的也可以,但是不规范
import java.io.*;
class FileRead43
{
public static void main(String[] args)
{
FileReader fr=null;
char[] ch=new char[1024];
int num=0;
try
{
fr=new FileReader("FileRead43.java");
while ((num=fr.read(ch))!=-1)
{
sop(new String(ch,0,num));
}
}
catch (IOException e)
{
sop(e.toString());
}
finally
{
try
{
if(fr!=null)
fr.close();
}
catch (IOException e)
{
sop(e.toString());
}
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
</span></span>
<span style="font-size:18px;"><span style="font-size:18px;">/*
实际应用:将C盘的一个文件复制到d盘中
【原理】
其实就是将C盘下的文件数据存储在d盘的一个文件中
具体步骤:
1.在d盘中创建一个文件,用于存储c盘的文件
2.定义一个读取流和将c盘的文件相关联
3.通过不断的数据读取完成数据的存储
4.关闭流资源
*/
import java.io.*;
class CopyText5
{
public static void main(String[] args)
{
//copy_1();
copy_2();
}
//第一种方式不介意使用,但是还是要掌握其思想,就是,读一个写一个……
//这样的效率并不高!
/*public static void copy_1() throws IOException
{
FileWriter fw=new FileWriter("d:\\copy_CopyText5.txt");
FileReader fr=new FileReader("c:\\CopyText5.java");
int ch=0;
while ((ch=fr.read())!=-1)
{
fw.write((char)ch);
}
fw.close();
fr.close();
}*/
//这种方式通过先读取在数组中的方法之,在统一的写入到指定的数据中去,
//优点:效率高效
public static void copy_2()
{
FileWriter fw=null;
FileReader fr=null;
char[] ch=new char[1024];
int num=0;
try
{
fw=new FileWriter("d:\\copy_CopyText5.txt");
fr=new FileReader("c:\\CopyText5.java");
while ((num=fr.read(ch))!=-1)
{
fw.write(ch,0,num);
}
}
catch (IOException e)
{
//sop(e.toString());专业的写法是下面这种,抛出一个运行时的异常提示
throw new RuntimeException("读写失败");
}finally
{
if (fw!=null)
{
try
{
fw.close();
}
catch (IOException e)
{
sop(e.toString());
}
}
if (fr!=null)
{
try
{
fr.close();
}
catch (IOException e)
{
sop(e.toString());
}
}
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
</span></span>
【总结】
其实最进本的数据输入和输出,最好理解的就是掌握其两个流:Reader抽象类和Writer抽象类(各自中的共性方法)
为了深入理解,我们可以通过其各自的子类去做一些相应的操作,例如上文中,我们主要进行的是对文件的操作,包括了其中的读,写的过程……主要用到了子类:FileRead和FileWriter两个具体的实现类来做……