一、概述
1.字符流的出现为了方便操作字符。
2.更重要的是加入了编码的转换,即转换流。
3.通过子类转换流来完成。在两个对象进行构造的时候,可以加入字符集(即编码表),可传入编码表的有:
(1)转换流:InuputStreamReader和OutputStreamWriter
(2)打印流:PrintStream和PrintWriter,只有输出流
编码表的由来
计算机只能识别二进制数据,早期由来是电信号。为了方便应用计算机,让它可以识别各个国家的文字。
就将各个国家的文字用数字来表示,并一一对应,形成一张表。这就是编码表。
常见的编码表:
(1)ASCII:美国标准信息交换码表。用一个字节的7位表示
(2)IOS8859-1:拉丁码表;欧洲码表。用一个字节的8位表示
(3)GB2312:中国的中文编码表()早期
(4)GBK:中国的中文编码表升级,融合了更多的中文文字字符。打头的是两个高位为1的两个字节编码。为负数
(5)Unicode:国际标准码,融合了多种文字。所有文字都用两个字节来表示,Java语言使用的就是unicode。
(6)UTF-8:Unicode Transformation Format
最多用三个字节表示一个字符的编码表,根据字符所占内存空间不同,分别用一个、两个、三个字节来编码。
二、转换流的编码应用
1.可以将字符以指定编码格式存储。
2.可以对文本数据指定编码格式来解读。
3.指定编码表的动作由构造函数完成。
三、编码和解码
1.编码:字符串变成字节数组
(1)默认字符集:
String ---> byte[] :srt.getBytes()
(2)指定字符集:
String ---> byte[] :srt.getBytes(charsetName)
2.解码:字节数组变成字符串
(1)默认字符集:
byte[] ---> String :new String(byte[])
(2)指定字符集:
byte[] ---> String :new String(byte[],charsetName)
四、对于编码和解码的字符集转换注意事项
1.如果编码失败,解码就没意义了。
2.如果编码成功,解码出来的是乱码,,则需对乱码通过再次编码(用解错码的编码表),然后再通过正确的编码表解码。针对于IOS8859-1是通用的。
3.如果用的是GBK编码,UTF-8解码,此时通过再次编码后解码的方式,就不能成功了,因为UTF-8也支持中文,在UTF-8解的时候,会将对应的字节数改变,所以不会成功。
4.特别注意:对于中文的”联通“,这两个字比较特别,它的二进制位正好是和在UTF-8中两个字节打头的相同,所以在文本文件中,
如果单独写“联通”或者和满足UTF-8编码格式的字符一起保存时,记事本就会用UTF-8来进行解码动作,这样显示的就会是乱码。
有五个学生,每个学生有3门课的成绩,
从键盘输入以上数据(包括姓名,三门课成绩),
输入的格式:如:zhagnsan,30,40,60计算出总成绩,
并把学生的信息和计算出的总分数高低顺序存放在磁盘文件"stud.txt"中。
步骤:
1,描述学生对象。
2,定义一个可操作学生对象的工具类。
思想:
1,通过获取键盘录入一行数据,并将该行中的信息取出封装成学生对象。
2,因为学生有很多,那么就需要存储,使用到集合。因为要对学生的总分排序。
所以可以使用TreeSet。
1.字符流的出现为了方便操作字符。
2.更重要的是加入了编码的转换,即转换流。
3.通过子类转换流来完成。在两个对象进行构造的时候,可以加入字符集(即编码表),可传入编码表的有:
(1)转换流:InuputStreamReader和OutputStreamWriter
(2)打印流:PrintStream和PrintWriter,只有输出流
编码表的由来
计算机只能识别二进制数据,早期由来是电信号。为了方便应用计算机,让它可以识别各个国家的文字。
就将各个国家的文字用数字来表示,并一一对应,形成一张表。这就是编码表。
常见的编码表:
(1)ASCII:美国标准信息交换码表。用一个字节的7位表示
(2)IOS8859-1:拉丁码表;欧洲码表。用一个字节的8位表示
(3)GB2312:中国的中文编码表()早期
(4)GBK:中国的中文编码表升级,融合了更多的中文文字字符。打头的是两个高位为1的两个字节编码。为负数
(5)Unicode:国际标准码,融合了多种文字。所有文字都用两个字节来表示,Java语言使用的就是unicode。
(6)UTF-8:Unicode Transformation Format
最多用三个字节表示一个字符的编码表,根据字符所占内存空间不同,分别用一个、两个、三个字节来编码。
二、转换流的编码应用
1.可以将字符以指定编码格式存储。
2.可以对文本数据指定编码格式来解读。
3.指定编码表的动作由构造函数完成。
三、编码和解码
1.编码:字符串变成字节数组
(1)默认字符集:
String ---> byte[] :srt.getBytes()
(2)指定字符集:
String ---> byte[] :srt.getBytes(charsetName)
2.解码:字节数组变成字符串
(1)默认字符集:
byte[] ---> String :new String(byte[])
(2)指定字符集:
byte[] ---> String :new String(byte[],charsetName)
四、对于编码和解码的字符集转换注意事项
1.如果编码失败,解码就没意义了。
2.如果编码成功,解码出来的是乱码,,则需对乱码通过再次编码(用解错码的编码表),然后再通过正确的编码表解码。针对于IOS8859-1是通用的。
3.如果用的是GBK编码,UTF-8解码,此时通过再次编码后解码的方式,就不能成功了,因为UTF-8也支持中文,在UTF-8解的时候,会将对应的字节数改变,所以不会成功。
4.特别注意:对于中文的”联通“,这两个字比较特别,它的二进制位正好是和在UTF-8中两个字节打头的相同,所以在文本文件中,
如果单独写“联通”或者和满足UTF-8编码格式的字符一起保存时,记事本就会用UTF-8来进行解码动作,这样显示的就会是乱码。
代码:
import java.io.*;
public class code
{
public static void main(String[] args) throws Exception {
String s = "王五";
byte[] b1 = s.getBytes("GBK");
System.out.println(Arrays.toString(b1));
String s1 = new String(b1, "utf-8");
System.out.println("s1="+s1);
byte[] b2 = s.getBytes("utf-8");
System.out.println(Arrays.toString(b2));
String s2 = new String(b2, "gbk");
System.out.println("s2="+s2);
//GBK utf-8 都识别中文,所以会解码不匹配
}
}
练习:
有五个学生,每个学生有3门课的成绩,
从键盘输入以上数据(包括姓名,三门课成绩),
输入的格式:如:zhagnsan,30,40,60计算出总成绩,
并把学生的信息和计算出的总分数高低顺序存放在磁盘文件"stud.txt"中。
步骤:
1,描述学生对象。
2,定义一个可操作学生对象的工具类。
思想:
1,通过获取键盘录入一行数据,并将该行中的信息取出封装成学生对象。
2,因为学生有很多,那么就需要存储,使用到集合。因为要对学生的总分排序。
所以可以使用TreeSet。
3,将集合的信息写入到一个文件中。
代码:
import java.io.*;
import java.util.*;
public class code
{
public static void main(String[] args) throws IOException {
Comparator<Student> cmp = Collections.reverseOrder();
Set<Student> stus = Stuinfotool.getStudents(cmp);
Stuinfotool.writeFile(stus);
}
}
class Student implements Comparable<Student>
{
private String name;
private int shuxue,yuwen,yingyu;
private int sum;
public Student(String name,int shuxue,int yinyu,int yuwen) {
this.name = name;
this.shuxue = shuxue;
this.yingyu = yingyu;
this.yuwen = yuwen;
sum = shuxue + yingyu + yuwen;
}
//成绩排序
public int compareTo(Student s) {
int num = new Integer(this.sum).compareTo(new Integer(s.sum));
if(num == 0)
return this.name.compareTo(s.name);
return num;
}
//hash存值
public int hashCode() {
return name.hashCode()+sum*12;
}
//判断类型
public boolean equals(Object obj) {
if(!(obj instanceof Student))
throw new ClassCastException("类型不匹配");
Student s = (Student)obj;
return this.name.equals(s.name) && this.sum==s.sum;
}
public String toString() {
return "student["+name+","+shuxue+","+yingyu+","+yuwen+"]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getShuxue() {
return shuxue;
}
public void setShuxue(int shuxue) {
this.shuxue = shuxue;
}
public int getYuwen() {
return yuwen;
}
public void setYuwen(int yuwen) {
this.yuwen = yuwen;
}
public int getYingyu() {
return yingyu;
}
public void setYingyu(int yingyu) {
this.yingyu = yingyu;
}
public int getSum() {
return sum;
}
public void setSum(int sum) {
this.sum = sum;
}
}
class Stuinfotool
{
public static Set<Student> getStudents() throws IOException{
return getStudents(null);
}
public static Set<Student> getStudents(Comparator<Student> cmp) throws IOException{
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
String len = null;
Set<Student> stus = null;
if(cmp==null)
stus = new TreeSet<Student>();
else
stus = new TreeSet<Student>(cmp);
while((len=bufr.readLine())!=null) {
if("over".equals(len))
break;
String[] info = len.split(",");
Student stu = new Student(info[0],
Integer.parseInt(info[1]) ,
Integer.parseInt(info[2]),
Integer.parseInt(info[3]));
stus.add(stu);
}
bufr.close();
return stus;
}
public static void writeFile(Set<Student> stus) throws IOException
{
BufferedWriter bufw = new BufferedWriter(new FileWriter("demo.txt"));
for(Student stu : stus) {
bufw.write(stu.toString()+"\t");
bufw.write(stu.getSum()+"");
bufw.newLine();
bufw.flush();
}
bufw.close();
}
}