Day 23开篇:
"今天java基础主要学习了io_遗留问题,高效字符流的概念,BufferedReader(Reader in),关于字节流读取中文乱码的问题,转换流的概念,转换流的简便类,jdk提供两种转换流分别是InputStreamReader和OutputStreamWriter等 "
知识点反馈:
今天的知识点总结的思维导图
一.io遗留问题
1. 高效字符流:
(1)概念:
从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取,可以指定缓冲区的大小,或者可使用默认的大小。大多数况下,默认值就足够大了
(2)BufferedReader(Reader in):创建一个高效读取字符流
(3)BufferedReader(Reader in, int sz):创建一个高效字读取符流,并指定缓冲区大小
BufferedReader仍然出现了乱码,怎么解决?使用FileInputStream的构造嵌套BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(new File("D:\\Input\\hello2.txt"));
(4)BufferedReader及BufferedWriter特有方法:
<1>BufferedReader--readLine():读取整行数据,返回一个字符串
<2>BufferedWriter--newLine():写入一个换行符
2. 关于字节流读取中文乱码的问题:
(1)为什么会乱码:
字符集编码: N个,基本上全世界的70%以上的国家都有自己语言的编码,有些国家甚至还有好几个GBK GB2312,所谓的字符集编码,就是这个编码的开发者,对一些文字的显示方式进行编码;因为每一个开发者的编码集的系统和处理方式不一致,所有不可能存在编码兼容的问题;utf-8 不兼容 gbk;gbk 不兼容 gb2312
(2)怎么去解决乱码的问题?
<1>使两个编码集进行兼容(不可能)
<2>使用某一种编码集进行读取或输出
(3)String(byte[] bytes, Charset charset):通过一个指定的(设置的)字符集编码去解码一个byte字节数组,转换为字符串
(4)byte[] getBytes(Charset charset):通过指定的(设置的)字符集编码,将一个字节转换为对于编码的字节数组
(5)byte[] -> String:解码操作,把看不懂的东西转换看的东西
(6)String -> byte[]:编码操作,将一个正常的字符串转换一个看不懂的字节
(7)关于编码:一般在实际的开发当中,请优先使用utf-8(因为utf-8又被称之为万国码,基本上这个星球能出现的语言,utf-8都有收录[不代表兼容])当然,在国内使用GB2312和GBK也不少
二.转换流
1. 概念:
其实就是一个正常的字节流通过一个指定的编码将看不懂的字节转换成我们看的懂字符
2. OutputStreamWrite:FileOutputStream + 编码表 = 字符
3. InputStreamReader:FileInputStream + 编码表 = 字符
4. 转换流的简便类:
(1)FileReader:FileOutputStream + 编码表 = 字符
(2)FileWriter:FileOutputStream + 编码表 = 字符
(3)优点:缩减了原来转换流的长度拼写的问题
(4)缺点:并没有提供任何的编码设置的方法,完全采用平台默认字符集
5.定义:转换流其实就是在字节流和字符流之间进行转换(并且可以直接的设置字符集编码)
6.jdk提供两种转换流:
(1)InputStreamReader:将InputStream(字节输入流)转换为Reader(字符输入流)
(2)OutputStreamWriter:将OutputStream(字节输出流)转换为Writer(字符输出流)
7.转换流出现的目的:
字节适用的场景是一个文件的读取数输出,字符适合的常见是文本内容的输入输出但是有的时候,可能当初定义的是一个字节的需求,后面某一个时刻或者场景需要切换为字符所以这个情况是没有办法明确定死是使用字节还是字符,那么就使用转换流
8. InputStreamReader:
(1)作用:实现了一个将字节输入流依照指定的字符集编码转换为字符输入流需要和InputStream套接使用
(2)构造:
<1>InputStreamReader(InputStream in):根据平台默认的字符集编码转换为字符流
<2>InputStreamReader(InputStream in, String charsetName):根据指定的字符集编码转换为字符流
(3)成员方法:
<1>int read():一次读取单个字符(两个字节)
<2>int read(char[] cbuf, int offset, int length):一次读取一个字符数组
9. OutputStreamWrite:
(1)作用:字节输出流转换为字符输出流
(2)构造:
<1>OutputStreamWriter(OutputStream out):根据平台默认的字符集编码写出数据
<2>OutputStreamWriter(OutputStream out, String charsetName):根据平台指定的字符集编码写出数据
(3)成员方法:
<1>void flush():刷新缓冲区
<2>除了这个刷新,基本功能完全参考OutputStream这里就不在描述(注意字节和字符的区分)
(4)close和flush()的区别
<1>close()关闭流对象,但是会先刷新一次,关闭之后此流不能继续使用
<2>flush()仅仅是刷新缓冲区,不会对流进行任何的操作
10. 练习:
(1)我们准备一个集合,存储多个字符串,请将集合里面的数据全部写到文本当中
public class Demo01 {
public static void main(String[] args) throws IOException {
ArrayList arrayList = new ArrayList();
arrayList.add("马化腾");
arrayList.add("马化腾");
arrayList.add("马化腾");
arrayList.add("马化腾");
arrayList.add("马化腾");
//将集合的数据写入到文本当中
BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\Input\\hello2.txt"));
//遍历集合并写出数据
for(String s : arrayList){
//写出数据
bw.write(s);
bw.newLine();
bw.flush();
}
bw.close();
}
}
(2)从文本读取所有的数据,存入到集合当中,并且遍历
public class Demo02 {
public static void main(String[] args) throws IOException {
//准备一个集合
ArrayList arrayList = new ArrayList();
//准备一个输入流
BufferedReader reader = new BufferedReader(new FileReader("D:\\Input\\hello2.txt"));
//读取数据写到集合
String line = null;
while ((line = reader.readLine()) != null){
arrayList.add(line);
}
reader.close();
for (String s : arrayList){
System.out.println(s);
}
}
}
(3)在一个文本当中定义10个名字,请实现随机点名
public class Demo03 {
public static void main(String[] args) throws Exception {
//创建一个集合
ArrayList arrayList = new ArrayList<>();
//读取文本名字
BufferedReader br = new BufferedReader(new FileReader("D:\\Input\\hello2.txt"));
//遍历文本
String line = null;
while ((line = br.readLine()) != null){
arrayList.add(line);
}
br.close();
Random r = new Random();
int index = r.nextInt(arrayList.size());
String name = arrayList.get(index);
System.out.println("幸运观众:"+name);
}
}
(4)键盘录入n个学生的信息
包含:
姓名
java成绩
Spring成绩
SQL成绩
JSP成绩
请将录入的信息存储到一个文本当中,并且实现平均成绩从小到大排序。并显示分数(10分钟)
姓名 | java成绩 | Spring成绩 | SQL成绩
public class Demo04 {
public static void main(String[] args) throws Exception {
//因为需要排序所以使用TreeSet
TreeSet ts = new TreeSet(new Comparator() {
@Override
public int compare(Student o1, Student o2) {
//比较平均分
int num = o2.getSum() - o1.getSum();
//如果平均分一致,根据Java分数进行排序
int num2 = (num == 0)? o1.getJava() - o2.getJava() : num;
//如果Java也一致
int num3 = (num2 == 0)? o1.getSpring() - o2.getSpring() : num2;
//如果Spring也一致
int num4 = (num3 == 0)? o1.getSql() - o2.getSql() : num3;
//如果Sql
int num5 = (num4 == 0)? o1.getJsp() - o2.getJsp() : num4;
//如果所有人的分数都一致
int num6 = (num5 == 0) ? o1.getName().compareTo(o2.getName()) : num5;
return num6;
}
});
//录入学生信息
for (int i = 0; i < 5; i++) {
System.out.println("请录入第"+i+"学生的信息:");
Scanner sc = new Scanner(System.in);
System.out.println("请输入姓名:");
String name = sc.next();
System.out.println("请输入Java:");
int java = sc.nextInt();
System.out.println("请输入Spring:");
int spring = sc.nextInt();
System.out.println("请输入sql:");
int sql = sc.nextInt();
System.out.println("请输入jsp:");
int jsp = sc.nextInt();
Student s = new Student();
s.setName(name);
s.setJava(java);
s.setJsp(jsp);
s.setSql(sql);
s.setSpring(spring);
ts.add(s);
}
//写入到文本当中
BufferedWriter bw = new BufferedWriter(new FileWriter("/Users/TOOBUG/Desktop/Java0413/第一阶段_JAVASE(入门必修)/Day23/第23天代码/test/demo.txt"));
bw.write("具体学生信息如下:");
bw.newLine();
bw.write("姓名--java成绩--sql成绩--spring成绩--jsp成绩");
bw.newLine();
for ( Student s : ts){
StringBuilder sb = new StringBuilder();
sb.append(s.getName()).append("--").append(s.getJava()).append("--").append(s.getSql())
.append("--").append(s.getSpring()).append("--").append(s.getJsp());
bw.write(sb.toString());
bw.newLine();
bw.flush();
}
bw.close();
System.out.println("成绩录入完毕");
}
}