IO流--文件流和缓冲流

文件流

文件字节流FileInputStream和FileOutputStream
  • FileInputStream和FileOutputStream是字节流,是节点流,数据源和目的地是文件。
  • 复制文件需要分别创建一个输入流和输出流进行文件读写。
  • 需要创建一个中转站,借助循环和中转站完成文件复制。
  • 流使用后一定要关闭,这和垃圾回收没有关系。

【示例1】:复制文件

public class TestCopy1 {
    public static void main(String[] args) throws IOException {
        //1.创建一个输入流和输出流
        InputStream fis =  new FileInputStream(new File("e:/readme.txt"));
        OutputStream fos = new FileOutputStream(new File("e:/readme2.txt"));
        //2.使用输入流和输出流完成文件复制
        //2.1准备一个中转站(水杯)
        int n;
        //2.2先读一个字节
        n = fis.read();//读取一个字节,赋给n
        while(n != -1){
            //2.3再写一个字节
            fos.write(n);
            //2.4在读一个字节
            n = fis.read();
        }     
        //3.关闭输入流和输出流
        fis.close();
        fos.close();
    }
}
  • 缺点:中转站太小,速度慢,效率低;复制更大的文件时效果更明显;可以将中转站从一个字节变为一个字节数组,减少读写硬盘的次数。
  • 问题:如果不是覆盖文件,而是追加内容,应该如何实现?

【示例2】复制文件(中转站是一个字节数组)

public class TestCopy2 {
    public static void main(String[] args) throws IOException {
        //1.创建流
//    InputStream fis = new FileInputStream(new File("e:/readme.txt"));
//    OutputStream fos = new FileOutputStream(new File("e:/readme.txt"));
        InputStream fis = new FileInputStream("e:/readme.txt");
        //OutputStream fos = new FileOutputStream("e:/readme2.txt");
        OutputStream fos = new FileOutputStream("e:/readme2.txt", true);//追加而不是覆盖
       //2.使用流
        //2.1准备一个中转站(水桶)
        byte [] buf = new byte[1024]; //2500=1024+1024+452
        //2.2 使用输入流从数据源读取数据到中转站
//读取数据到中转站,数据在数组中转站中,返回的真正读取的字节数
        int len = fis.read(buf);
        while(len !=-1 ){
            //2.3使用输出流把中转站数据写到到目的文件
            //fos.write(buf);//将buf中转站内容写到文件中
            fos.write(buf, 0, len);
            //2.4在读一次
            len = fis.read(buf);
        }                
        //3.关闭流
        fis.close();
        fos.close();
    }
}

文件字符流FileReader和FileWriter

  • FileReader和FileWriter是字符流,节点流,数据源和目的地是文件。

【示例3】复制文件(中转站是一个字符)

public class TestCopy3 {
    public static void main(String[] args) throws IOException {
        //创建流
        Reader fr = new FileReader("e:/readme.txt");
        Writer fw = new FileWriter(new File("e:/readme2.txt"));
        //使用流
        //中转站是一个字符
   //先读一个
        int n=  fr.read();//使用输入流读取一个字符char !!,不是字节
        while(n!=-1){
            //输出
            System.out.println((char)n);
            //写一个
            fw.write(n);
            //再读一个
            n = fr.read();       
        }
        //关闭流
        fr.close();
        fw.close();
    }
}

【示例4】复制文件(中转站是一个字符数组,并进行异常处理)

public class TestCopy4 {
    public static void main(String[] args) {
        //创建流     
        Reader fr = null;
        Writer fw = null;
        try {
            fr = new FileReader("e:/readme.txt");
            fw = new FileWriter(new File("e:/readme2.txt"));
            //使用流
            //更大的中转站
            char[] cbuf = new char[1024];
            //读取的多个字符放入cbuf,返回的是读取的字符的个数
            int len = fr.read(cbuf);
            while (len != -1) {
                //写
                //fw.write(cbuf); 
                //fw.write(cbuf, 0, len);
                fw.write(new String(cbuf, 0, len));
                //再读
                len = fr.read(cbuf);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭流
            try {
                if (fr != null) {
                    fr.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fw != null) {
                    fw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 其实只有字节流,没有字符流。字符流的底层还是字节流,进行了封装转换,使开发者可以更简单的来处理非英文字符。
  • 字节流可以完成所有类型文件的复制(文本、音频、视频、图片、chm);字符流只能完成文本文件的复制(txt、java),doc不是文本文件;字符流一般用来处理包含中文的文本文件。
  • 异常处理的分析:创建流、使用流要使用一次try-catch语句,关闭流要分开进行异常处理。

缓冲流

缓冲字节流BufferedInputStream和BufferedOutputStream

【示例5】复制文件(使用缓冲流字节流提高效率)

public class TestCopy5 {
    public static void main(String[] args) throws IOException {
        //1.创建一个输入流和输出流
      InputStream fis = 
                new FileInputStream(new File("e:/JDK_API.CHM"));
      OutputStream fos = 
                new FileOutputStream(new File("e:/JDK_API2.CHM"));
//默认输入缓冲区大小8192
      BufferedInputStream bis = new BufferedInputStream(fis); 
//默认输出缓冲区大小8192
      BufferedOutputStream bos = new BufferedOutputStream(fos);       
        //2.使用输入流和输出流完成文件复制
        //2.1准备一个中转站(水杯)
        int n;
        //2.2先读一个字节
        n = bis.read();//读取一个字节,赋给n
        while(n != -1){
            //在控制台显示该字节
            //System.out.println((char)n);
            //2.3再写一个字节
            bos.write(n);
            //2.4在读一个字节
            n = bis.read();
        }
        //3.关闭输入流和输出流
        //bos.flush();
        bis.close();
        bos.close();
    }
}
  • 缓冲流的原理

在这里插入图片描述

  • 只要关闭高层流即可,底层流不用手动关闭;因为高层的关闭方法就是将底层流关闭。
  • 如何刷新输出缓冲区(让缓冲区内容写入硬盘,保证一致)
    1.满了就自动刷新
    2.bos.close()先flush,再关闭(关闭的时候会先刷新)
    3.手动刷新flush()

缓冲字符流BufferedReader和BufferedWriter

  • 问题:之前的文件读写都是按照字节、字符或者数组来实现的,对于文本文件而言,能否按照行,一行行读写呢?
  • 提供了BufferedReader和BufferedWriter实现按行读写。

【示例6】复制文件(按行读写)

public class TestCopy6 {
    public static void main(String[] args) throws IOException {
         //创建两个流
        BufferedReader br = 
       new BufferedReader(new FileReader(new File("e:/sqlnet.log")));
        BufferedWriter bw = 
                new BufferedWriter(new FileWriter("e:/sqlnet2.log"));
        
        //使用两个流完成按行读取的功能
        //中转站就是一个字符串,存储一行数据
        //先读一行
        String str =  br.readLine();
        while(str != null ){
            //再写一行
            bw.write(str);
            //bw.write("\r\n");不同操作系统中换行符是不同的
            bw.newLine();
            //再读一行
            str = br.readLine();//!!!
        }
        //关闭两个流
        br.close();
        bw.close();
    }
}

总结1:BufferedReader和BufferedWriter的优点
1.速度快
2.简化编程
总结2:readLine()底层的原理
底层还是一个一个字符的读取,append()放入到StringBuilder(或者char[] )中,遇到换行符 ,将StringBuilder(char[])转换成String并返回
总结3:不同的操作系统中换行符是不同的
Unix系统里,每行结尾只有“<换行>”,即“\n”;
Windows系统里面,每行结尾是“<回车><换行>”,即“\r\n”;
Mac系统里,每行结尾是“<回车>”,即“\r”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值