java学习笔记290-308 字符流,字符流和ArrayList相结合

前言
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文件改进版
分析:
- 转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,可以使用子类简化书写。
FileReader(String fileName)
: 用于读取字符文件的便携类。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();
}
}
}