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

一、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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值