Java|IO流之字符流

在这里插入图片描述

1. 字符流出现的原因

由于字节流操作中文不是特别方便,所以,java就提供了字符流。
字符流 = 字节流 + 编码表
常见编码表:

  • ASCII
  • Unicode
  • GB2312
  • UTF-8

2. String类中的编码和解码

编码: 就是把字符串转换成字节数组 String ===> byte[]

  • public byte[] getBytes();
    使用平台的默认字符集将此 String编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
  • public byte[] getBytes(String charsetName)
    使用指定的字符集将此 String 编码为 byte 序列,并将
		String s="hahahaha";
        byte[] bytes = s.getBytes();
        System.out.println(bytes);

        byte[] gbks = s.getBytes("GBK");
        System.out.println(gbks);

解码: 把字节数组转换成字符串 bytes[] ===> String

  • public String(byte[] bytes):
    通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
  • public String(byte[] bytes, String charsetName)
    通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String
		String s1 = new String(bytes);
        System.out.println(s1);

        String s2 = new String(gbks, "GBK");
        System.out.println(s2);

3. 字符转换流:InputStreamReader

InputStreamReader:
字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

构造方法:

  • 1.InputStreamReader(InputStream in)
    创建一个使用默认字符集的 InputStreamReader。
  • 2.InputStreamReader(InputStream in, String charsetName)
    创建使用指定字符集的 InputStreamReader。
		InputStreamReader reader = new InputStreamReader(new FileInputStream("bb.txt"));

成员方法

  • 1.public int read()
    一次读取一个字符
  • 2.public int read(char[] cbuf)
    一次读取一个字符数组 如果没有读到 返回-1
        char[] chs = new char[1024];
        reader.read(chs);
        System.out.println(String.valueOf(chs));
        reader.close();

4. 字符转换流:OutputStreamWriter

OutputStreamWriter:
字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。
它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
构造方法:

  • 1.OutputStreamWriter(OutputStream out)
    创建使用默认字符编码的 OutputStreamWriter。

  • 2.OutputStreamWriter(OutputStream out, String charsetName)
    创建使用指定字符集的 OutputStreamWriter。
    成员方法:

  • 1.public void write(int c)
    写一个字符

  • 2.public void write(char[] cbuf)
    写一个字符数组

  • 3.public void write(char[] cbuf,int off,int len)
    写一个字符数组的 一部分

  • 4.public void write(String str)
    写一个字符串

  • 5.public void write(String str,int off,int len)
    写一个字符串的一部分

 		writer1.write("abc");
        //字符流必须要刷新
        writer1.flush();
        writer1.write("\r\n");
        writer1.flush();
        writer1.write("222");
        writer1.flush();
        writer1.write("222");
        writer1.flush();

        //刷新并关闭
        writer1.close();
        writer2.close();

注意:
1.字符流必须要刷新;
2.close()实际完成了刷新并关闭流的功能
3.如果文件不大,close()就够用了;如果文件很大,有几百G,就需要flush().

5. 字符转换流的子类:FileReader和FileWriter

转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,所以,为了简化我们的书写,转换流提供了对应的子类。

转换流便捷类
OutputStreamWriterFileWriter
InputStreamReaderFileReader

转换流与便捷类的唯一区别是:便捷类不能指定编码

示例:用便捷流复制文件

		//用便捷流复制文件
        FileReader reader = new FileReader("copydemo.java");
        FileWriter writer = new FileWriter("copydemo(2).java");

        char[] chars = new char[1024];
        int len=0;
        while ((len=reader.read(chars))!=-1){
            writer.write(chars,0,len);
            writer.flush();
        }
        reader.close();
        writer.close();

6. 字符缓冲流:BufferedReader 和 BufferedReader

BufferedWriter
构造方法:

  • public BufferedWriter(Writer w)

特殊的成员方法:

  • BufferedWriter: public void newLine():
    根据系统来决定换行符 具有系统兼容性的换行符

BufferedReader
构造方法:

  • public BufferedReader(Reader e)

特殊的成员方法:

  • BufferedReader: public String readLine():
    一次读取一行数据 是以换行符为标记的 读到换行符就换行 没读到数据返回null;包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null

示例:字符缓冲流的特殊功能复制文本文件(一行一行复制)

		BufferedReader reader = new BufferedReader(new FileReader("copydemo.java"));
        BufferedWriter writer = new BufferedWriter(new FileWriter("copydemo(3).java"));
        String line=null;
        while ((line=reader.readLine())!=null){
            writer.write(line);
            writer.newLine();     //换行符,具有平台兼容性
            writer.flush();
        }
        reader.close();
        writer.close();

7. 几个示例

7.1 把ArrayList集合中的字符串数据存储到文本文件

		 //1.把ArrayList集合中的字符串数据存储到文本文件
        ArrayList<String> list = new ArrayList<>();
        list.add("abc");
        list.add("cde");
        list.add("fff");

        FileOutputStream out = new FileOutputStream("list.txt");
        for (String s : list) {
            out.write(s.getBytes());
            out.write("\r\n".getBytes());
            out.flush();
        }
        out.close();

7.2 把文本文件中的数据(每一行为一个字符串数据)存储到集合中

		//2.把文本文件中的数据(每一行为一个字符串数据)存储到集合中
        BufferedReader reader = new BufferedReader(new FileReader("copydemo.java"));
        ArrayList<String> list = new ArrayList<>();

        String line=null;
        while ((line=reader.readLine())!=null){
            list.add(line);
        }
        reader.close();

        for (String s : list) {
            System.out.println(s);
        }

7.3 有一个文本文件,每一行是一个学生的名字,请写一个程序,每次允许随机获取一个学生名称

		//3.有一个文本文件,每一行是一个学生的名字,请写一个程序,每次允许随机获取一个学生名称
        ArrayList<String> list = new ArrayList<>();

        BufferedReader reader = new BufferedReader(new FileReader("studentName.txt"));

        String line=null;
        while ((line=reader.readLine())!=null){
            list.add(line);
        }

        reader.close();

        Random random = new Random();
        int i = random.nextInt(list.size());
        System.out.println(list.get(i));

7.4 复制多级文件夹,如果有文件夹内有.png的文件,把后缀名改为.jpg

package exerciseDemo;

import java.io.*;

public class MyTest4 {
    public static void main(String[] args) throws IOException {
        //复制文件夹,如果有文件夹内有.png的文件,把后缀名改为.jpg
        File fileSource = new File("multiDemo");
        System.out.println(fileSource.exists());
        File fileTarget = new File("multiDomoAndRename");
        if(!fileTarget.exists()){
            fileTarget.mkdir();
        }
        fileCopyAndRename(fileSource,fileTarget);


    }

    private static void fileCopyAndRename(File fileSource, File fileTarget) throws IOException {
        //复制一个文件夹,并文件夹内有.png的文件,把后缀名改为.jpg
//        FileInputStream in = new FileInputStream(fileSource);
//        FileOutputStream out = new FileOutputStream(fileTarget);
        File[] files = fileSource.listFiles();
        for (File file : files) {
            if(file.isFile()){
                //如果是文件
                if(file.getName().endsWith(".png")){
                    String newfileName = file.getName().replace(".png", ".jpg");
                    File filenew = new File(fileTarget, newfileName);
                    copyFunc(file,filenew);

                }else{
                    File file1 = new File(fileTarget, file.getName());

                    copyFunc(file,file1);
                }

            }else if(file.isDirectory()){
                 //如果是文件夹,递归处理

                 //新建一个文件夹
                File file1 = new File(fileTarget, file.getName());
                file1.mkdir();

                //复制

                fileCopyAndRename(file,file1);

            }

        }


    }

    private static void copyFunc(File fileSource, File fileTarget) throws IOException {
        //复制一个文件

        FileInputStream in = new FileInputStream(fileSource);
        FileOutputStream out = new FileOutputStream(fileTarget);

        byte[] bytes = new byte[1024 * 8];
        int len=0;
        while ((len=in.read(bytes))!=-1){
            out.write(bytes,0,len);
            out.flush();
        }
        in.close();
        out.close();
    }
}

7.5 键盘录入3个学生信息(姓名, 语文成绩 数学成绩, 英语成绩, 按照总分从高到低存入文本文件

package exerciseDemo;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Comparator;
import java.util.Date;
import java.util.Scanner;
import java.util.TreeSet;

public class MyTest5 {
    public static void main(String[] args) throws IOException {
        //  键盘录入3个学生信息(姓名, 语文成绩(chineseScore),
        //  数学成绩(mathScore), 英语成绩(englishScore)), 按照总分从高到低存入文本文件
        //  方式0:每次写入,覆盖上次的内容
        //  方式1.追加写入
        //  方式2.每次写入一个新的文件,文件名包含时间信息
        TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                //按照总分排大小
                int num= s1.totalScore()-s2.totalScore();
                //再比较姓名
                int num2=num==0?s1.getName().compareTo(s2.getName()):num;
                return num2;
            }
        });




        for (int i = 1; i <= 3; i++) {
            Student student = new Student();
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入"+i+"个学生的姓名");
            String name = scanner.nextLine();
            student.setName(name);
            System.out.println("请输入" + i + "个学生的语文成绩");
            int yw = scanner.nextInt();
            student.setChineseScore(yw);
            System.out.println("请输入" + i + "个学生的数学成绩");
            int xs= scanner.nextInt();
            student.setMathScore(xs);
            System.out.println("请输入" + i + "个学生的英语成绩");
            int yy = scanner.nextInt();
            student.setEnglishScore(yy);
            //把学生添加到集合里面去
            treeSet.add(student);
        }

        // 方式0:每次写入,覆盖上次的内容
        // BufferedWriter writer = new BufferedWriter(new FileWriter("Student.txt"));

        // 方式1.追加写入
         //BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("Student.txt",true)));

        // 方式2.每次写入一个新的文件文件名包含时间信息
        long l = System.currentTimeMillis();
        Date date = new Date(l);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy_MM_dd_HH:mm:ss");
        String format = simpleDateFormat.format(date);
        String filename="Student_".concat(format);
        BufferedWriter writer = new BufferedWriter(new FileWriter(filename));

        //收到写一样表头
        writer.write("编号"+"\t"+"姓名"+"\t"+"语文"+"\t"+"数学"+"\t"+"外语"+"\t"+"总分");
        writer.newLine();
        writer.flush();

        //遍历集合把学生的数据存到文本文件中
        int index=1;
        for (Student student : treeSet) {
            writer.write(index+"\t"+student.getName()+"\t"+student.getChineseScore()+"\t"+student.getMathScore()+"\t"+student.getEnglishScore()+"\t"+student.totalScore());
            writer.newLine();
            writer.flush();
            index++;

        }
        writer.close();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值