前言

b站java课程学习笔记整理。

b站视频: 黑马程序员全套Java教程_Java基础入门视频教程,零基础小白自学Java必备教程

290. 为什么出现字符流

一个汉字的存储:如果是GBK编码,占用两个字节,如果是UTF-8编码,占用三个字节。

如果传输一个汉字,假如是UTF-8,那么就是三个字节的数据。在控制台转成char后把这三个字节转成了字符,就会“乱码”。

字符流= 字节流 + 编码表。

用字节流复制文本文件时,文本文件有中文也没有问题,原因是底层操作会自动进行字节拼接。汉字在存储时,第一个字节都是负数。

291.编码表

计算机中的信息都是二进制数组成的。

  • 按照某种规则,将字符存储到计算机中,成为编码。反之,按照某种规则,将存储的二进制数解析显示出来,成为解码。

  • 字符编码: 就是一套自然语言的字符与二进制数之间的对应规则。例如(A,65).

字符集:

  • 是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等
  • 计算机要标准的存储和识别各种字符集符号,就需要进行字符编码,一套字符集必然至少有一套字符编码。常见的有ASCII字符集、GBXXX字符集,Unicode字符集等。

ASCII

基本的ASCII字符集使用7位表示一个字符,共128字符。

GBK

最常用的中文码表。

UTF-8

统一码,万国码,业界规则。

  • US-ASCII:一个字节编码
  • 拉丁文:两个字节
  • 大部分常用字(含中文):三个字节
  • 其他极少使用的辅助字符: 四个字节

292. 字符串中的编码解码问题

编码:

  • byte[] getBytes() : 使用默认字符集将String编码为一系列字节,将结果存储到新的字节数组中。
  • byte[]getBytes(String charsetName): 使用指定的字符集将该String编码为一系列字节,将结果存储到新的字节数组中。

解码:

  • String(byte[] bytes): 使用默认字符集解码构建新的String
  • String(byte[] bytes, String charsetName): 通过指定的字符集解码指定的字节数组来构造新的String
package 编码与解码;


import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

public class StringDemo {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String s = "中国";
        byte[] bys = s.getBytes(StandardCharsets.UTF_8);
        System.out.println(Arrays.toString(bys)); //[-28, -72, -83, -27, -101, -67]
        String line = new String(bys);
        System.out.println(line); //中国

        bys = s.getBytes("GBK");
        System.out.println(Arrays.toString(bys)); //[-42, -48, -71, -6]
        line = new String(bys); //使用的UTF-8解码,出现问题 �й�
        System.out.println(line);
        line = new String(bys,"GBK");// 中国
        System.out.println(line);


    }
}

293. 字符流中的编码解码问题

字符流抽象基类:

  • Reader:字符输入流的抽象类
  • Writer:字符输出流的抽象类

字符流中和编码解码问题相关的两个类:

  • InputStreamReader
  • OutputStreamWriter
package 字符流中的编码解码;

import java.io.*;
import java.nio.charset.StandardCharsets;

public class Demo {
    public static void main(String[] args) throws IOException {
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("idea_test\\java.txt"),
                StandardCharsets.UTF_8);
        osw.write("中国");
        osw.close();

        InputStreamReader isr = new InputStreamReader(new FileInputStream("idea_test\\java.txt"),
                StandardCharsets.UTF_8);

        // 和字节流是一样的,一次读取一个或者一次读取一个字符数组
        char[] line = new char[1024];
        int len;
        while ((len = isr.read(line))!=-1){
            System.out.println(new String(line, 0, len));
        }
        isr.close();

    }
}

294. 字符流写数据的5种方式

方法名 说明
void write(int c) 写一个字符
void write(char[] cbuf) 写一个字符数组
void write(char[] cbuf, int off, int len) 写字符数组的一部分
void write (String str) 写一个字符串
void write(String str, int off, int len) 写一个字符串的一部分
flush() 刷新流
close() 刷新后关闭流
package 字符流写数据的五种方法;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class Demo {
    public static void main(String[] args) throws IOException {
        OutputStreamWriter osw= new OutputStreamWriter(new FileOutputStream("idea_test\\java.txt"));

        osw.write(97);
        osw.flush();

        char[] chs = {'a', 'b', 'c', 'd', '中'};
        osw.write(chs);
        osw.flush();

        osw.write(chs,1,3);
        osw.flush();

        osw.write("theshy来全杀了");
        osw.flush();

        String s = "Rookie尽力了";
        osw.write(s,1,3);
        osw.flush();
        
        osw.close();
    }
}

295. 字符流读数据的两种方式

方法名 说明
int read() 一次读一个字符
int read(char[] cbuf) 一次读一个字符数组数据
package 字符流读字符;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class Demo {
    public static void main(String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("idea_test\\java.txt"));

/*        int ch;
        while ((ch = isr.read())!=-1){
            System.out.println((char)ch);
        }*/

        System.out.println("---------------");

        char[] chars = new char[1024];
        int len;
        while ((len = isr.read(chars))!=-1){
            System.out.println(new String(chars, 0, len));
        }
        isr.close();




    }
}

总结:

字节流和字符流的方式是一样的。只不过字符流更方便复制字符。

296. 字符流复制Java文件

案例:复制java文件。

package 字符流复制Java文件;

import java.io.*;

public class Demo {
    public static void main(String[] args) throws IOException {
        String source = "E:\\Javacode\\JavaSE Code\\rookie\\rookie.java";
        String destination = "E:\\Javacode\\JavaSE Code\\theshy\\theshy.java";

        InputStreamReader isr = new InputStreamReader(new FileInputStream(source));
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(destination));
		
        // 还是两种方法,复制字符或者字符数组。
        char[] chars = new char[1024];
        int len;
        while ((len = isr.read(chars))!=-1){
            osw.write(chars,0,len);
        }
        isr.close();
        osw.close();

    }
}

297. 字符流复制Java文件改进版

分析:

  1. 转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,可以使用子类简化书写。
  2. FileReader(String fileName): 用于读取字符文件的便携类。
  3. FileWriter(String fileName): 用于写入字符文件的便携类。
package 字符流复制java文件改进;
import java.io.*;
public class Demo {
    public static void main(String[] args) throws IOException {
        String source = "E:\\Javacode\\JavaSE Code\\rookie\\rookie.java";
        String destination = "E:\\Javacode\\JavaSE Code\\theshy\\theshy.java";

        FileReader fr = new FileReader(source);
        FileWriter fw = new FileWriter(destination);

        //用法和那个麻烦的一样,就是简洁了而已。
        char[] chars = new char[1024];
        int len;
        while ((len = fr.read(chars))!=-1){
            fw.write(chars,0,len);
        }

        fr.close();
        fw.close();

    }
}

就是简洁的换了个类名。

298. 字符缓冲流

类似于字节缓冲流。

  • BufferedWriter(Write out)
  • BufferedReader(Read in)
package 字符缓冲流;

import java.io.*;

public class Demo {
    public static void main(String[] args) throws IOException {
        String source = "E:\\Javacode\\JavaSE Code\\rookie\\rookie.txt";
        String destination = "E:\\Javacode\\JavaSE Code\\theshy\\theshy.txt";


        BufferedReader br = new BufferedReader(new FileReader(destination));
        BufferedWriter bw = new BufferedWriter(new FileWriter(source));

        bw.write("theshy来全杀了");
        bw.write("\n");   //好像我的windows是\n
        bw.write("rookie尽力了");

        char[] chars = new char[1024];
        int len;
        while ((len = br.read(chars))!=-1){
            System.out.println(new String(chars,0,len));
        }

        bw.close();
        br.close();
    }
}

299. 字符缓冲流复制java文件

package 字符缓冲流复制java文件;

import java.io.*;

public class Demo {
    public static void main(String[] args) throws IOException {
        String source = "E:\\Javacode\\JavaSE Code\\rookie\\rookie.java";
        String destination = "E:\\Javacode\\JavaSE Code\\theshy\\theshy.java";


        BufferedReader br = new BufferedReader(new FileReader(destination));
        BufferedWriter bw = new BufferedWriter(new FileWriter(source));

        char[] chars = new char[1024];
        int len;
        while ((len = br.read(chars))!=-1){
            bw.write(chars,0,len);
        }

        bw.close();
        br.close();
    }
}

300. 字符缓冲流的特有功能

BufferedWriter:

  • void newLine():写一行行分隔符(对于本电脑说白了就是/n),行分隔符字符串由系统属性定义。

BufferedReader:

  • public String readLine():读一行文字,结果包含行的内容的字符串,不包括任何行终止字符,如果流结尾已经到达则为null
package 字符缓冲流复制java文件;

import java.io.*;

public class Demo {
    public static void main(String[] args) throws IOException {
        String source = "E:\\Javacode\\JavaSE Code\\rookie\\rookie.txt";
        String destination = "E:\\Javacode\\JavaSE Code\\theshy\\theshy.txt";


        BufferedReader br = new BufferedReader(new FileReader(destination));
        BufferedWriter bw = new BufferedWriter(new FileWriter(source));

        for(int i = 0; i<10;i++){
            bw.write("rookie尽力了"+i);
            bw.newLine();
            bw.flush();
        }

        String line;
        while((line = br.readLine())!=null){
            System.out.print(line); //没有换行
            System.out.println(line);
        }


        bw.close();
        br.close();
    }
}

301. 字符缓冲流的特有功能复制java文件

package 字符缓冲流复制java文件;

import java.io.*;

public class Demo {
    public static void main(String[] args) throws IOException {
        String source = "E:\\Javacode\\JavaSE Code\\rookie\\rookie.java";
        String destination = "E:\\Javacode\\JavaSE Code\\theshy\\theshy.java";


        BufferedReader br = new BufferedReader(new FileReader(destination));
        BufferedWriter bw = new BufferedWriter(new FileWriter(source));

        String line;
        while((line = br.readLine())!=null){
            bw.write(line);
            bw.newLine();
            bw.flush();
        }


        bw.close();
        br.close();
    }
}

302. IO流小结

总结: 多用缓冲流,最好用字符缓冲流的特有功能,方便简洁。

303. 集合到文件

需求:把ArrayList集合中的字符串数据写入到文本文件。要求:每一个字符串元素作为文件中的一行数据。

package 集合到文件;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

public class Demo {
    public static void main(String[] args) throws IOException {
        String source = "idea_test\\java.txt";

        ArrayList<String> al = new ArrayList<>();
        al.add("theshy来全杀了");
        al.add("rookie尽力了");
        al.add("wink状态");

        BufferedWriter bw = new BufferedWriter(new FileWriter(source));

        for(String string:al){
            bw.write(string);
            bw.newLine();
            bw.flush();
        }

        bw.close();
    }
}

304. 文件到集合

需求:把文本文件中的语句写入到ArrayList集合。要求:文件中的每一行数据是一个集合元素。

package 文件到集合;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

public class Demo {
    public static void main(String[] args) throws IOException {
        String source = "idea_test\\java.txt";

        ArrayList<String> al = new ArrayList<>();

        BufferedReader br = new BufferedReader(new FileReader(source));

        String line;
        while((line = br.readLine())!=null){
            al.add(line);
        }
        System.out.println(al);

        br.close();
    }
}

305. 点名器

需求:从txt文件中读取学生名单,控制台随机点一个人的名字。

package 点名器;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;

public class Demo {
    public static void main(String[] args) throws IOException {
        String source = "idea_test\\java.txt";

        ArrayList<String> al = new ArrayList<>();

        BufferedReader br = new BufferedReader(new FileReader(source));

        String line;
        while((line = br.readLine())!=null){
            al.add(line);
        }
        br.close();

        Random r = new Random();
        String name = al.get(r.nextInt(al.size()));
        System.out.println(name);

    }
}

306. 集合到文件的改进版

需求:把ArrayList集合中的学生数据写入到文本文件。要求:每一个学生对象的数据作为文件中的一行数据。

格式:学号,姓名,年龄,居住地

package 集合到文件的改进版;

public class Student {
    private String name;
    private int age;
    private String id;
    private String address;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Student(){}

    public Student(String name, int age,String id, String address){
        this.age = age;
        this.name = name;
        this.address = address;
        this.id = id;
    };


}

package 集合到文件的改进版;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

public class Demo {
    public static void main(String[] args) throws IOException {
        ArrayList<Student> al = new ArrayList<>();
        Student s1 = new Student("Jiangeng Sun",24,"2016160061","Heilongjiang");
        Student s2 = new Student("Jiansun Sun",23,"2016160062","Heilongjiang");

        al.add(s1);
        al.add(s2);

        String source = "idea_test\\java.txt";
        BufferedWriter bw = new BufferedWriter(new FileWriter(source));

        for(Student student:al){
            bw.write(student.getName());
            bw.write(", ");
            bw.write(String.valueOf (student.getAge()));
            bw.write(", ");
            bw.write(student.getId());
            bw.write(", ");
            bw.write(student.getAddress());
            bw.write(", ");
            bw.newLine();
            bw.flush();
        }

        bw.close();
    }
}

老师用的StringBuilder做的,感觉老师的方法更好。

307. 文件到集合改进版

需求:把文本文档中的数据读取到集合中,并遍历。

package 文件到集合改进版;

public class Student {
    private String name;
    private int age;
    private String id;
    private String address;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Student(){}

    public Student(String name, int age,String id, String address){
        this.age = age;
        this.name = name;
        this.address = address;
        this.id = id;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", id='" + id + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

package 文件到集合改进版;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

public class Demo {
    public static void main(String[] args) throws IOException {
        ArrayList<Student> al = new ArrayList<>();
        String source = "idea_test\\java.txt";


        BufferedReader br = new BufferedReader(new FileReader(source));

        String line;
        while((line = br.readLine())!=null){
            String[] strArr = line.split(",");

            Student s = new Student();
            s.setName(strArr[0]);
            s.setAge(Integer.parseInt(strArr[1]));
            s.setId(strArr[2]);
            s.setAddress(strArr[3]);

            al.add(s);
        }

        br.close();

        for(Student student: al){
            System.out.println(student);
        }
    }
}

308. 集合到文件数据排序改进版

需求:按照总分、数学、语文、英语、姓名依次排序。

package 集合到文件数据排序改进版;

public class Student {
    private String name;
    private int Chinese;
    private int Math;
    private int English;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getChinese() {
        return Chinese;
    }

    public void setChinese(int chinese) {
        Chinese = chinese;
    }

    public int getMath() {
        return Math;
    }

    public void setMath(int math) {
        Math = math;
    }

    public int getEnglish() {
        return English;
    }

    public void setEnglish(int english) {
        English = english;
    }

    public Student(String name, int math, int chinese, int english) {
        this.name = name;
        Chinese = chinese;
        Math = math;
        English = english;
    }

    public Student() {
    }

    public int Sum(){
        int ChineseScore = getChinese();
        int MathScore = getMath();
        int EnglishScore = getEnglish();

        return ChineseScore+MathScore+EnglishScore;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", Chinese=" + Chinese +
                ", Math=" + Math +
                ", English=" + English +
                '}';
    }
}

package 集合到文件数据排序改进版;

import java.io.*;
import java.util.Comparator;
import java.util.TreeSet;

public class Demo{
    public static void main(String[] args) throws IOException {
        TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                int s1Sum = s1.Sum();
                int s2Sum = s2.Sum();

                int sumFlag = s1Sum - s2Sum;

                int mathFlag = sumFlag == 0? s1.getMath()-s2.getMath() : sumFlag;
                int ChineseFlag = mathFlag == 0? s1.getChinese()-s2.getChinese():mathFlag;
                int EnglishFlag = ChineseFlag == 0? s1.getEnglish()-s2.getEnglish():ChineseFlag;
                return EnglishFlag == 0? s1.getName().compareTo(s2.getName()):EnglishFlag;

            }

        });

        ts.add(new Student("李维瀚",95,94,93));
        ts.add(new Student("孙健耕",91,94,93));
        ts.add(new Student("施霁桐",95,91,93));
        ts.add(new Student("李安然",92,94,93));

        BufferedWriter br = new BufferedWriter(new FileWriter("idea_test\\java.txt"));

        for(Student student: ts){
            StringBuilder sb = new StringBuilder();
            sb.append(student.getName()).append(",").append(student.getMath()).append(",")
                    .append(student.getChinese()).append(",").append(student.getEnglish());

            br.write(sb.toString());
            br.newLine();
            br.flush();
        }

    }


}