前言
b站java课程学习笔记整理。
b站视频: 黑马程序员全套Java教程_Java基础入门视频教程,零基础小白自学Java必备教程
290. 为什么出现字符流
一个汉字的存储:如果是GBK
编码,占用两个字节,如果是UTF-8
编码,占用三个字节。
如果传输一个汉字,假如是UTF-8
,那么就是三个字节的数据。在控制台转成char
后把这三个字节转成了字符,就会“乱码”。
字符流= 字节流 + 编码表。
用字节流复制文本文件时,文本文件有中文也没有问题,原因是底层操作会自动进行字节拼接。汉字在存储时,第一个字节都是负数。
291.编码表
计算机中的信息都是二进制数组成的。
字符集:
- 是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等
- 计算机要标准的存储和识别各种字符集符号,就需要进行字符编码,一套字符集必然至少有一套字符编码。常见的有
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)); String line = new String(bys); System.out.println(line);
bys = s.getBytes("GBK"); System.out.println(Arrays.toString(bys)); line = new String(bys); 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"));
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文件改进版
分析:
- 转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,可以使用子类简化书写。
FileReader(String fileName)
: 用于读取字符文件的便携类。
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"); 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(); }
}
}
|