Reader/Writer字符流概述和使用方法

字符流

  • Reader
  • Writer
FileReader/Writer

练习:使用FileReader和Writer复制文件

注意:字符流和字节流的使用过程是一样的,唯一不同的地方在于字节流是使用byte数组接受读取的数据,而字符流是使用char数组接受读取的数据

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;

public class Demo2 {
    public static void main(String[] args) throws IOException {
        //创建第一个文件
        File srcfile = new File("沁园舂 雪.txt");
        srcfile.createNewFile();
        String string = "沁园春·雪\n" +
                "作者:毛泽东\n" +
                "\n" +
                "北国风光,千里冰封,万里雪飘。\n" +
                "望长城内外,惟余莽莽;大河上下,顿失滔滔。\n" +
                "山舞银蛇,原驰蜡象,欲与天公试比高。\n" +
                "须晴日,看红装素裹,分外妖娆。\n" +
                "江山如此多娇,引无数英雄竞折腰。\n" +
                "惜秦皇汉武,略输文采;唐宗宋祖,稍逊风骚。\n" +
                "一代天骄,成吉思汗,只识弯弓射大雕。\n" +
                "俱往矣,数风流人物,还看今朝。";
        //在第一个文件中写入数据
        FileWriter fw = new FileWriter(srcfile);
        fw.write(string);
        fw.close();

        //创建第二个文件
        File destfile = new File("沁园春.txt");
        //创建读入流和写出流
        FileReader fr = new FileReader(srcfile);
        FileWriter fw2 = new FileWriter(destfile);
        //字符流需要用char字符数组进行读写
        char[] chars = new char[1024];
        int len;
        while((len=fr.read(chars))!=-1){
            fw2.write(chars);
        }
        //关闭流
        fr.close();
        fw2.close();
    }
}
BufferedReader/Writer

字符缓冲流,性质和用法与字节缓冲流相似

练习:使用字符缓冲流复制文件

import java.io.*;

public class Demo3 {
    public static void main(String[] args) throws IOException {
        //创建File对象
        File srcfile = new File("沁园舂 雪.txt");
        File destfile = new File("沁园春 梅.txt");
        //创建FileReader和FIleWriter,然后创建BufferedReader和BufferedWriter
        BufferedReader br = new BufferedReader(new FileReader(srcfile));
        BufferedWriter bw = new BufferedWriter(new FileWriter(destfile));
        //读写
        //方法一使用数组读写
        char[] chars = new char[10];
        int len;
        while ((len=br.read(chars))!=-1){
            bw.write(chars,0,len);
        }
        bw.close();
        br.close();

        //方法二使用readLine方法
        File srcfile2 = new File("沁园舂 雪.txt");
        File destfile2 = new File("沁园春 兰.txt");
        BufferedReader br2 = new BufferedReader(new FileReader(srcfile2));
        BufferedWriter bw2 = new BufferedWriter(new FileWriter(destfile2));
        String data;
        while((data=br2.readLine())!=null){
            bw2.write(data);
            bw2.newLine();
        }
        //关闭流
        bw2.close();
        br2.close();
    }
}

案例:集合到文件

需求:键盘录入5个学生信息(姓名,语文,数学,英语成绩)。要求按照成绩总分从高到低写入文本文件

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.Buffer;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;

public class Demo14 {
    public static void main(String[] args) throws IOException {
        //创建TreeSet集合,通过比较器排序
        TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                int num1 = o2.getSum() - o1.getSum();
                int num2 = num1==0?o2.getYuwen()-o1.getYuwen():num1;
                int num3 = num2==0?o2.getShuxue()-o1.getShuxue():num2;
                int num4 = num3==0?o2.getName().compareTo(o1.getName()):num3;
                return num4;
            }
        });
        //键盘录入数据
        for (int i=0;i<3;i++){
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入第"+(i+1)+"个同学的信息:");
            System.out.print("姓名:");
            String name = sc.nextLine();
            System.out.print("语文成绩:");
            int chinese = sc.nextInt();
            System.out.print("数学成绩:");
            int math = sc.nextInt();
            System.out.print("英语成绩:");
            int english = sc.nextInt();

            Student stu = new Student(name,chinese,math,english);
            ts.add(stu);
        }

        //创建字符缓冲输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("achievement.txt"));

        //遍历集合得到每个学生对象
        String str = "姓名 语文 数学 英语 总分\n";
        bw.write(str);
        bw.flush();
        for (Student stu:ts){
            StringBuilder sb = new StringBuilder();
            sb.append(stu.getName()+" ").append(stu.getYuwen()+" ").append(stu.getShuxue()+" ").append(stu.getYingyu()+" ").append(stu.getSum());
            bw.write(sb.toString());
            bw.newLine();//换行
            bw.flush();
        }
        //释放资源
        bw.close();
    }
}

练习:分别使用节点流:FileInputStream、FIleOutputStream和缓冲流:BufferedInputStream、BufferedOutputStream实现文本文件/图片/视频的肤质,并比较在数据复制方面的效率

import java.io.*;

public class Demo4 {
    public static void main(String[] args) throws IOException {
        File src = new File("齐天大圣.mp4");
        File dest = new File("美猴王.mp4");
        File dest2 = new File("弼马温.mp4");
        copy1(src,dest);
        copy2(src,dest2);
    }

    private static void copy2(File src, File dest) throws IOException {
        long start = System.currentTimeMillis();
        FileInputStream fis = new FileInputStream(src);
        FileOutputStream fos = new FileOutputStream(dest);
        BufferedInputStream bis = new BufferedInputStream(fis);
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        byte[] bytes = new byte[1024];
        int len;
        while ((len=bis.read(bytes))!=-1){
            bos.write(bytes);
        }
        long end = System.currentTimeMillis();
        System.out.println("缓冲(处理)流的复制速度为:"+(end-start));
    }

    public static void copy1(File src, File dest) throws IOException {
        long start = System.currentTimeMillis();
        FileInputStream fis = new FileInputStream(src);
        FileOutputStream fos = new FileOutputStream(dest);
        byte[] bytes = new byte[1024];
        int len;
        while ((len=fis.read(bytes))!=-1){
            fos.write(bytes);
        }
        fos.close();
        fis.close();
        long end = System.currentTimeMillis();
        System.out.println("文件流的复制速度为:"+(end-start));
    }

}
/*
文件流的复制速度为:197
缓冲(处理)流的复制速度为:44
*/

练习:实现图片加密操作

import java.io.*;
import java.nio.Buffer;

public class Demo5 {
    public static void main(String[] args) throws IOException {
        int pass = 2;
        File src = new File("jiaoyuan.png");
        File dest = new File("教员.png");
        encryption(src,dest);
    }

    //加密复制一个图片
    private static void encryption(File src, File dest) throws IOException {
        FileInputStream fis = new FileInputStream(src);
        FileOutputStream fos = new FileOutputStream(dest);
        BufferedInputStream bis = new BufferedInputStream(fis);
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        int date;
        while((date=bis.read())!=-1){
            bos.write(date*5);
        }
        bis.close();
        bos.close();
    }
}

练习:获取文本上每个字符出现的次数

提示:遍历文本的每一个字符,以及出现的次数保存在Map中,将Map中数据写入文件

import sun.awt.SunHints;

import java.io.*;
import java.nio.BufferOverflowException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class Demo6 {
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("沁园春.txt");
        FileWriter fw = new FileWriter("统计.txt");
        BufferedReader br = new BufferedReader(fr);
        BufferedWriter bw = new BufferedWriter(fw);
        //创建TreeMap
        Map<Character,Integer> map = new HashMap<>();
        int i=0;
        while((i = br.read())!=-1){
            char c = (char) i;
            if (map.get(c)==null){
                map.put(c,1);
            }else{
                map.put(c,map.get(c)+1);
            }
        }
        Set<Map.Entry<Character,Integer>> setKey = map.entrySet();
        for (Map.Entry<Character, Integer> key:setKey){
            switch (key.getKey()){
                case ' ':
                    bw.write("空格:"+key.getValue());
                    break;
                case '\t':
                    bw.write("tab:"+key.getValue());
                    break;
                case '\n':
                    bw.write("换行:"+key.getValue());
                    break;
                case '\r':
                    bw.write("回车:"+key.getValue());
                    break;
                default:
                    bw.write(key.getKey()+":"+key.getValue());
                    break;
            }
            bw.newLine();
        }
        br.close();
        bw.close();
    }
}