2021-10-19

IO流

在这里插入图片描述
IDEA中:
说明:如果大家使用JUnit中的单元测试方法测试,相对路径即为当前Module下。
如果大家使用main()测试,响度路径即为当前的Project下。
Eclipse中:
不管使用单元测试方法还是使用main()测试,相对路径都是当前的Project下。
在这里插入图片描述
File类的使用:路径分隔符
在这里插入图片描述
常用方法:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
IO流原理及流的分类
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
字节流:byte 适用于图片,视频
字符流:char 适用于文本
字节流:就是两个节点中的流
处理流:就是在流上边再加上一个流(作用加快流的速度)
流的分类图示:在这里插入图片描述
IO流体系:
在这里插入图片描述
在这里插入图片描述
读取硬盘中文文件,并打印在控制台:

package com.atguigu.java;

import org.junit.Test;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class FileReaderWriterTest {
    /*public static void main(String[] args) {
        File file = new File("hello.txt");//相较于当前路径
        System.out.println(file.getAbsoluteFile());//D:\Program Files\project\JavaSenior\hello.txt

        File file1 = new File("day01\\hello.txt");
        System.out.println(file.getAbsoluteFile());//D:\Program Files\project\JavaSenior\day09\hello.txt
    }
*/
   @Test
    public void testFileReader() throws IOException {
       //1.实例化File类的对象,指明要操作的文件
       File file = new File("hello.txt"); //相较于当前module
        //2.提供数据的流
       FileReader fr = new FileReader(file);

       //3.数据的读入
       //read();返回读入的一个字符。如果达到文件末尾,返回-1
      /* int data = fr.read();//char类型就是其实也是一个 int a=97
       while (data!=-1){
           System.out.print((char) data);
           data = fr.read();
       }*/
       //方式二
       //3.数据的读入
       int data;
       while ((data= fr.read())!=-1){
           System.out.println((char) data);
       }
       //流的关闭
       fr.close();
   }
}

说明点:
1.异常的处理:为了保证流资源一定可以执行关闭操作。需要使用try-catch-finally处理。
2.read();返回读入的一个字符。如果达到文件末尾,返回-1。
3.读入的文件一定能够要存在,否则就会报FileNotFoundException。
关于异常的捕获这里,如果在外面没有实例化就报错了(FileReader fr = null; File file = new File("hello.txt"); //相较于当前module //2.提供数据的流 fr = new FileReader(file);
)。读入的文件如果没有,那就直接出来了,所以我们这里最后要加一个判断。
在这里插入图片描述
模板:
后续主要是2,3不同;流的使用,输入和输出。
在这里插入图片描述
在这里插入图片描述
上图结果,为下面的输出;
在这里插入图片描述
正确演示:
方法一(循环的方法):
在这里插入图片描述
方法二(String字符串的方法):
在这里插入图片描述

@Test
    public void testFileRead01() throws IOException {
       //File类的实例化
       File file = new File("hello.txt");
       //流的实例化
       FileReader fr = new FileReader(file);
       //读入操作
       //read(char[]cBuffer):返回读入cBuffer数组中的字符的个数。如果达到文件末尾,返回-1
       char[] cBuffer = new char[5];
       int len;
       while ((len=fr.read(cBuffer))!=-1){
           //方式一
           //读进了几个就输出几个
         /*  for (int i = 0; i < len; i++) {
               System.out.print(cBuffer[i]);
           }

*/
           //方式二
           String str = new String(cBuffer,0,len);
           System.out.print(str);

       }
       //资源的关闭
       fr.close();
   }

字符流写出的操作:

@Test
    public void testFileWriter() throws IOException {
        //1.提供File类的对象,指明要写出到的文件文件名
        File file = new File("hello1.txt");


        //2.提供FileWriter的对象,用于数据的写出
        FileWriter fw = new FileWriter(file);


        //3.写出的操作
        fw.write("i have a dream\n");
        fw.write("you need have a dream too");


            //4.流资源的关闭
        fw.close();


    }

说明:输出操作,对应的File可以存在也可以不存在。
如果不存在,在输出的过程中,会自动创建文件。
如果存在,且//2.提供FileWriter的对象,用于数据的写出 FileWriter fw = new FileWriter(file,false);则覆盖该文件;
如果存在,且//2.提供FileWriter的对象,用于数据的写出 FileWriter fw = new FileWriter(file,true);则在该文件后面继续添加。

读入和写出文件代码(文件的复制):

@Test
    public void fileWriterFileReader(){
        FileReader fir = null;
        FileWriter fow = null;
        try {
            //1.创建File类的对象,指明读入和写出的文件
            File fi = new File("hello.txt");
            File fo = new File("helle2.txt");

            //2.创建输入流和输出流的对象
            fir = new FileReader(fi);
            fow = new FileWriter(fo);
            //3.数据的读入和写出操作
            char[] cBuffer = new char[5];
            int len;
            while ((len=fir.read(cBuffer))!=-1){
                fow.write(cBuffer,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4关闭流资源
            try {
                if (fow!=null)
                fow.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fir!=null)
                fir.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

这里是两种关闭流第二种写法,第二个流关闭有没有在finally里面try、catch一样。
在这里插入图片描述
对于文本文件的英语是可以用字节流去读的(但不建议),但是对于中文就不可以了有可能会出现乱码。是因为一个中文是用多个字节组成的。
结论:对于文本文件(.txt,.java,.c,.cpp),使用字符流处理;
对于非文本文件(.jpg,.mp3,.mp4,.avi,.doc,.ppt…),使用字节流处理。
图片文件的复制代码:

package com.atguigu.java;

import org.junit.Test;

import java.io.*;

public class FileInputOutputStreamTest {
    @Test
    public void testFileInputOutputStream(){
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            File fi = new File("QQ图片20211018170403.png");
            File fo = new File("QQ图片202110181704031.png");

            fis = new FileInputStream(fi);
            fos = new FileOutputStream(fo);

            byte[] buffer = new byte[5];
            int len;
            while((len=fis.read(buffer))!=-1){
                fos.write(buffer,0,len);
            }
            System.out.println("复制成功");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {if (fos!=null)
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {if (fis!=null)
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

视频的复制,这里我们把复制当做一个方法封装起来。就是把上一个代码里的实参,改为形参。代码如下:

    @Test
    public void testCopyFile(){
        String srcPath = "C:\\Users\\47641\\Desktop\\011.mkv";
        String destPath ="C:\\Users\\47641\\Desktop\\012.mkv";
        long start = System.currentTimeMillis();
        copyFile(srcPath,destPath);
        long end = System.currentTimeMillis();
        System.out.println("复制操作花费的时间"+(end-start));//复制操作花费的时间11419

    }
    public void copyFile(String srcPath,String destPath){
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            File fi = new File(srcPath);
            File fo = new File(destPath);

            fis = new FileInputStream(fi);
            fos = new FileOutputStream(fo);

            byte[] buffer = new byte[1024];//通常这里是写1024,这个地方写多少运行时间是有区别的。
            int len;
            while((len=fis.read(buffer))!=-1){
                fos.write(buffer,0,len);
            }
            System.out.println("复制成功");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {if (fos!=null)
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {if (fis!=null)
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

文本文件只要不在内存中读(就是不要去操作),可以用字节流,就是直接复制。就是相当于搬运工,原原本本的样子,还是0和1.然后再拿出去
但是非文本文件就不可以用字符流复制。
缓冲流(处理流的一种)
1.缓冲流:
BufferedInputStream
BufferedOuputStream
BufferedReader
BufferedWriter
2.作用:提高流的读取、写入的速度 ;
3.处理流就是“套接”在已有的流的基础上;
4.关闭资源时,同一级别的顺序无所谓。不同级别的后开先关。(先关外层流,后关内层流)说明:关闭外层流的同时,内层流会自动关闭。关于内层流的关闭,我们可以省略。
缓冲流复制代码:

package com.atguigu.java;

import org.junit.Test;

import java.io.*;

public class BufferedTest {
    @Test
    public void bufferStream(){
        FileInputStream fis = null;
        FileOutputStream fos = null;
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            //1.造文件
            File srcFile = new File("QQ图片202110181704031.png");
            File destFile = new File("QQ图片202110181704034.png");
            //2.造流
            //2.1造节点流
            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);
            //2.2造缓冲流
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);
            //3.复制的细节,读取,写入
            byte[] buffer = new byte[10];//就是把buffer看做是一个小车,拿它来给两点之间运东西
            int len;
            while((len= bis.read(buffer))!=-1){
                bos.write(buffer,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally { //资源关闭
            try {if (bos!=null)
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {if (bis!=null)
                bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {if (fos!=null)
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();  
            }
            try {if (fis!=null)
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

缓冲流复制视频代码(与上一个的时间对比):

package com.atguigu.java;

import org.junit.Test;

import java.io.*;

public class BufferedTest {
    @Test
    public void bufferStream(){
        FileInputStream fis = null;
        FileOutputStream fos = null;
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            //1.造文件
            File srcFile = new File("QQ图片202110181704031.png");
            File destFile = new File("QQ图片202110181704034.png");
            //2.造流
            //2.1造节点流
            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);
            //2.2造缓冲流
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);
            //3.复制的细节,读取,写入
            byte[] buffer = new byte[10];//就是把buffer看做是一个小车,拿它来给两点之间运东西
            int len;
            while((len= bis.read(buffer))!=-1){
                bos.write(buffer,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally { //资源关闭
            try {if (bos!=null)
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {if (bis!=null)
                bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {if (fos!=null)
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {if (fis!=null)
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    //实现文件复制;用缓冲流
    public void copyFile(String srcPath,String destPath){
        FileInputStream fis = null;
        FileOutputStream fos = null;
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            //1.造文件
            File srcFile = new File(srcPath);
            File destFile = new File(destPath);
            //2.造流
            //2.1造节点流
            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);
            //2.2造缓冲流
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);
            //3.复制的细节,读取,写入
            byte[] buffer = new byte[1024];//就是把buffer看做是一个小车,拿它来给两点之间运东西
            int len;
            while((len= bis.read(buffer))!=-1){
                bos.write(buffer,0,len);
            }
            System.out.println("文件复制完毕");
        } catch (IOException e) {
            e.printStackTrace();
        } finally { //资源关闭
            try {if (bos!=null)
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {if (bis!=null)
                bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {if (fos!=null)
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {if (fis!=null)
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    @Test
    public void testCopyFile(){
        String srcPath = "C:\\Users\\47641\\Desktop\\011.mkv";
        String destPath = "C:\\Users\\47641\\Desktop\\013.mkv";
        long start = System.currentTimeMillis();
        copyFile(srcPath,destPath);
        long end = System.currentTimeMillis();
        System.out.println("复制操作花费的时间"+(end-start));//复制操作花费的时间3978
    }
}


bos.flush()//这个是BufferedOutputStream()里面的刷新缓冲区的方法;有的缓冲流是没有自动刷新的。

字符流复制:

/*

    使用BufferedReader和BufferedWriter实现文本文件的复制
     */
    @Test
    public void testBufferedReaderBufferedWriter() throws IOException {
        BufferedReader br = new BufferedReader(new FileReader(new File("dbcp.txt")));
        BufferedWriter bw = new BufferedWriter(new FileWriter(new File("dbcp2.txt")));
        //读写操作 方法一使用char[]数组
        /*char[] chars = new char[1024];
        int len;
        while((len= br.read(chars))!=-1){
            bw.write(chars,0,len);
        }*/

        //方法二使用String
        String data;
        while((data = br.readLine())!=null){
            bw.write(data);//data中不包含换行符,如果要换行就是自己加bw.write(data+“\n”);
            //还有一个方法就是利用方法换行 bw.newLine();
            bw.newLine();}
        bw.close();
        br.close();
        }
    }


缓冲流习题1:
在这里插入图片描述

图片的加密解密(就是对字节进行变换在还原):

package com.atguigu.exer;

import org.junit.Test;

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

public class PicTest {
    @Test
    //图片加密
    public void testSecurity() throws IOException {
        FileInputStream fis = new FileInputStream("QQ图片20211018170403.png");
        FileOutputStream fos  = new FileOutputStream("QQ图片202110181704038secret.png");

        byte[] buffer = new byte[1024];
        int len;
        while((len= fis.read(buffer))!=-1){
            //加密操作(这里是用亦或)
            for (int i = 0; i < len; i++) {
                buffer[i] = (byte) (buffer[i] ^5);
            }
            fos.write(buffer,0,len);
        }
        fos.close();
        fis.close();
    }
    @Test
    //图片解密
    public void testSolve() throws IOException {
        FileInputStream fis = new FileInputStream("QQ图片202110181704038secret.png");
        FileOutputStream fos  = new FileOutputStream("QQ图片202110181704038solve.png");

        byte[] buffer = new byte[1024];
        int len;
        while((len= fis.read(buffer))!=-1){
            //解密操作(这里是用亦或)亦或的亦或就是原来的
            for (int i = 0; i < len; i++) {
                buffer[i] = (byte) (buffer[i] ^5);//m^n^n=m;
            }
            fos.write(buffer,0,len);
        }
        fos.close();
        fis.close();
    }
}

获取文本上每个字符出现的次数(遍历文本的每一个字符:字符及出现的次数保存在Map中;将Map中数据写入文件):

package com.atguigu.exer;

import org.junit.Test;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class WordTest {
    @Test
    public void testCountWord() throws IOException {
        //1.创建一个Map集合
        HashMap<Character, Integer> map = new HashMap<>();
        //2.遍历每一个字符,每一个字符出现的次数放到map中
        FileReader fr = new FileReader("dbcp.txt");
        int c = 0;
        while ((c= fr.read())!=-1){
            //int 还原char
            char ch = (char)c;
            //判断char是否在map中第一次出现
            if (map.get(ch)==null){
                map.put(ch,1);
            }else{
                map.put(ch,map.get(ch)+1);
            }
        }
        //3.吧map中数据存在文件count。txt
        //3.1创建Writer
        BufferedWriter bw = new BufferedWriter(new FileWriter("wordCount.txt"));
        //3.2遍历map,在写入数据
        Set<Map.Entry<Character, Integer>> entrySet = map.entrySet();
        for (Map.Entry<Character, Integer> entry : entrySet) {
            switch (entry.getKey()){
                case' ':
                    bw.write("空格="+entry.getValue());
                    break;
                case '\t':
                    bw.write("tab键="+entry.getValue());
                    break;
                case'\r':
                    bw.write("回车="+entry.getValue());
                    break;
                case'\n':
                    bw.write("换行="+entry.getValue());
                    break;
                default:
                    bw.write(entry.getKey()+"="+entry.getValue()
                    );
                    break;
            }
            bw.newLine();
        }
        fr.close();
        bw.close();

    }
}

备注一下集合知识:
对于Map集合类,map是用于存储元素对,即通过“键”和“值”来存储元素,每个键对应着一个值,对使用 containsKey() 和 containsValue() 遍历 HashMap 中所有元素所需时间的测试表明,containsValue() 所需的时间要长很多。 因此,如果 containsValue() 是应用程序中的性能问题,它将很快显现出来,并可以通过监测您的应用程序轻松地将其识别。 这种情况下,我相信您能够想出一个有效的替换方法来实现 containsValue() 提供的等效功能, 但如果想不出办法,则一个可行的解决方案是再创建一个 Map,并将第一个 Map 的所有值作为键。 这样,第一个 Map 上的 containsValue() 将成为第二个 Map 上更有效的 containsKey()。
然后通过将Map转成set就可以迭代。 map有一个方法叫做entrySet,这方法可以将Map的键值对的映射关系作为set集合的元素存储到Set集合当中,而这种映射关系的类型就是Entry的类型。因此可以通过使用Getkey()和getvalue()两个方法得到Set中存储的键和值。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值