(82)IO概述、字符流写入、异常处理、续写、两种读取方式、读写练习

来源:互联网 发布:石油化工数据 编辑:程序博客网 时间:2024/06/05 15:01

一、IO流概述
IO流用来处理设备之间的数据传输
Java对数据的操作是通过流的方式
Java用于操作流的对象都是在IO包中
流按照操作数据分为两种:字节流、字符流
流按流向分为:输入流、输出流
二、IO流常用基类
①字节流的抽象基类:InputStream ,OutputStream
②字符流的抽象基类:Reader、Writer
注意:由这四类派生出来的子类名称都是以其父类作为子类名的后缀
如:InputStream的子类FileInputStream
Reader的子类FileReader
三、IO字符流
既然IO流是用于操作数据的,所以数据的最常见体现形式是:文件
那么先以操作文件为主来演示
需求:在硬盘上,创建一个文件并写入一些文字数据
找到一个专门用于操作文件的Writer子类对象:FileWriter,后缀名是父类名,前缀名为该流对象的功能。
FileWriter类的构造函数没有不含参数的原因:要想操作文件,必须现有文件。即该流对象一一初始化,就必须保证文件存在
java.lang.Object
——–java.io.Writer
——–java.io.OutputStreamWriter
———java.io.FileWriter

以下演示的是创建流、输入流(以及输入到文件中)、关闭流进行演示,这些步骤记住

package Demo;import java.io.*;public class Demo {    public static void main(String[] args)throws IOException {        /*创建一个FileWriter对象,该对象一被初始换,就必须含有被操作的文件        *而且该文件会创建到指定的目录下,如果该目录下有同名文件,将被覆盖        *其实该步就是在明确数据要存放的目的地        */        FileWriter fw=new FileWriter("demo.txt");        //调用write方法,将字符串写入流(流在内存的缓冲区中)中        //调用flush方法,就能将流中的数据,存入到文件(目的地)中        fw.write("adhuwifcb");        fw.flush();        /*注意每次写入,都必须flush        *关闭流资源,但是关之前会默认刷新一次内存的缓冲区中的数据。        *将数据刷到目的地。        *和flush的区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭        */        fw.write("hahah");        fw.close();        fw.write("ooooooo");//流关闭,不能再将数据写入流中,更不能写入文件中    }}

IO处理方式标准解决方式

import java.io.*;public class IOexception {    public static void main(String[] args) {        /*         * 在io操作中,都会抛出异常,但是不能每个操作都trycatch         * 原因是:比如文件创建不成功,若解决了这个问题,相当于将该问题隐藏         * 之后的操作都无效,因为文件都没建立起来,写还有关等其他操作都没意义,不用再执行了         */        FileWriter fw=null;//必须在外建立引用,否则在finally中fw无法识别        try {         fw=new FileWriter("demo.txt");        fw.write("bjdi");        }        catch(IOException e) {            System.out.println(e.toString());        }        /*         * 注意不论操作成功,还是操作异常,被catch捕获,最终都要把流关闭         * 但是关资源,也会发生异常,所以要单独try下         */        finally {            try {                if(fw!=null)/*                             *  写if 的原因是若文件流创建不成功,则fw就还是null,没有指向谁,就无从谈起关闭了,                             *  若不写该句,会抛出NullPointerException异常                             */                { fw.close();}            } catch (IOException e) {                System.out.println(e.toString());            }        }    }}

因为上面的代码带有解释,比较乱。所以下面再写个纯代码形式

public static void main(String[] args) {    FileWriter fw=null;    try {        fw=new FileWriter("k:\\demo.txt");        fw.write("bjdi");        }    catch(IOException e) {        System.out.println(e.toString());         }    finally {        try {            if(fw!=null)              fw.close();         } catch (IOException e) {            System.out.println(e.toString());        }    }}   }

文件的续写:就是在原来文件内容的基础上,继续写内容:
public FileWriter(String fileName, boolean append) throws IOException
fileName:一个字符串,表示与系统有关的文件名
append:一个boolean值,如果为true,则将数据写入文件末尾处,而不是写入文件开始处

  public class Demo3 {public static void main(String[] args) {    FileWriter  fw=null;    try {      fw=new FileWriter("demo.txt",true);//在构造函数处指定文件,确定是否续写      fw.write("kkkkkkkkk");//在文本的末尾写       fw.write("nihao\r\nheihei");//记事本中\r\n为换行。写入字符串      char[] ch= {'h','e','l','l','o'};//也可以写入字符数组      fw.write(ch);       }    catch(IOException e) {        System.out.println(e.toString());      }    finally {        try {             if(fw!=null)               fw.close();        }        catch(IOException e) {            System.out.println(e.toString());        }    }  }}

java.lang.Object
——–java.io.Reader
——–java.io.InputStreamWriter
———java.io.FileReader

文本读取的第一种方式

     /*创建一个文件读取流对象并且指定名称的文件相关联     * 要保证该文件是已经存在的,如果不存在,会发生FileNotFoundException(io异常的子类)异常     */    FileReader fr=new FileReader("demo.txt");    System.out.println("----------读取的第一种方式----------------");    /*     * 调用读取流对象的read方法     * read():一次读一个字符,而且会自动往下读     */    int ch=0;//到达流的末尾返回-1,所以有了循环的条件    while((ch=fr.read())!=-1) {        System.out.println("ch="+(char)ch);    }

这里写图片描述
说明:reader()方法每次读一个,读完一个字符后,指针自动到文本的下一个字符,直到字符的末尾 返回-1。所以可以用用结尾字符-1作为循环条件,输出文本所有数据

文本读取的第二种方式

System.out.println("----------读取的第二种方式----------------");    /*     * 通过字符数组进行读取     */    //定义一个字符数组,用于存储读到的字符,该read(char[])返回的是字符个数    char[] buf=new char[3];    int num=fr.read(buf);    System.out.println("num="+num+new String(buf));    int num1=fr.read(buf);    System.out.println("num1="+num1+new String(buf));    int num2=fr.read(buf);    System.out.println("num2="+num2+new String(buf));

这里写图片描述
public int read(char[] cbuf):返回读取的字符数,如果到达流的末尾,则返回-1

说明:左图为流,右图为存放字符的数组,有三个空间。
①开始时,流指针指向a,将a存入ch[0]中,读出后,流指针和数组指针均向后移。
此时,流指针指向b,将b存入ch[1]中,读出后,流指针和数组指针均向后移。
此时,流指针指向c,将c存入ch[2]中,读出后,流指针和数组指针均向后移,数组指向-1,已经存不下数据了,所以不会再在从流中读取数据,并且read(char[])=3,返回存的个数。
②再次调用read(char[ ])由①知流指针指向d,数组的指针在末尾自动返回到ch[0](因为它向一个数组里面装数据),所以将def存入数组,之后,流指针指向g,数组指针指向末尾,read(char[])=3。
③再次调用read(char[ ])由②知,流指针指向g,数组指针执行ch[0],所以将g存入ch[0]中,流指针指向-1,没数据不能再读了,所以read(char[])=1(只读了一个数据),在打印的时候,打印的是数组字符串,所以打印gef
因为只读到了一个,所以取出这一个就可以了。
int num1=fr.read(buf);
System.out.println(“num1=”+num1+new String(buf,0,num1));//这样就只输出个g
【public String(char[] value, int offset, int count)】
offset:初始偏移量
count:长度

④再次调用read(char[ ])由③知,流指针指向-1,没有数据可读,read(char[])=-1(没读数据,返回-1),打印的还是字符数组,所以仍然是gef.
第二种读取的循环形式:

char[] buf=new char[3];    int num=0;    while((num=fr.read(buf))!=-1) {        System.out.println("num="+num+"   "+new String(buf,0,num));    }输出:num=3   abc     num=3   def     num=1   g

在实际开发中,字符数组char[] buf=new char[1024];短的可以一次就打印完,长的也可以减少循环数。
两种读取方式中第二种比较好,因为它可以有效减少循环次数,方式一循环次数太多。

练习:将c盘的一个文件复制到d盘中
复制的原理:
1,在D盘创建一个文件,用于存储c盘文件的数据
2,定义读取流和c盘文件相关联
3,通过不断的读写完成数据存储
4,关闭资源

import java.util.*;import java.io.*;public class Demo4 {    public static void main(String[] args)  {        FileWriter fw=null;        FileReader fr=null;        try {        fw=new FileWriter("DemoCopy.java");        fr=new FileReader("C:\\Demo.java");        int num=0;        char[] buf=new char[1024];        while ((num=fr.read(buf))!=-1) {            fw.write( buf,0,num);//可以写数组            fw.flush();              }        }        catch(IOException e) {            throw new RuntimeException("读写失败");        }        finally {             try {                 if(fw!=null)                      fw.close();             }catch(IOException e) {                 throw new RuntimeException("原文件关闭失败");             }             try {                 if(fr!=null)                      fr.close();             }catch(IOException e) {                 throw new RuntimeException("复制后关闭失败");             }        }    }}

图示表示这个复制过程
这里写图片描述

阅读全文
0 0
原创粉丝点击