前言

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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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() 刷新后关闭流
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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) 一次读一个字符数组数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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): 用于写入字符文件的便携类。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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集合中的字符串数据写入到文本文件。要求:每一个字符串元素作为文件中的一行数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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集合。要求:文件中的每一行数据是一个集合元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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文件中读取学生名单,控制台随机点一个人的名字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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集合中的学生数据写入到文本文件。要求:每一个学生对象的数据作为文件中的一行数据。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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;
};


}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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. 文件到集合改进版

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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 + '\'' +
'}';
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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. 集合到文件数据排序改进版

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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 +
'}';
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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();
}

}


}