黑马程序员java基础篇----字符编码
2013-04-07 17:53
246 查看
android培训java培训期待与您交流
一、编码解码&码表
1、常见的编码表:
ASCII:美国标准信息交换码---用一个字节的7位可以表示。
ISO8859-1:拉丁码表---欧洲码表用一个字节的8位表示,负数。
GB2312:中国的中文编码表---每个文字用两个字节表示,两个都是负数,且该码表兼容ASCII码表。
GBK:中国的中文编码表升级,融合了更多的中文文字符号---同上。
Unicode:国际标准码,融合了多种文字---所有文字都用两个字节来表示,Java语言使用的就是unicode
UTF-8:根据投标来确定是用一个、两个还是三个字节来表示一个字符。
2、编码与解码:
编码 字符串---->字节数组
解码 字节数组---->字符串
二、转换流与码表的融合
1、InputStreamReader:字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
OutputStreamWriter:字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
2、转换流工作原理:
程序执行流程按下图①-⑤所示的顺序进行:
三、乱码异常分析
1、UTF-8&GBK相关异常
本程序运行结果如下:
这种情况的其实就是编码码表与解码码表的不一致性引起的,而且这中间也是有规律可循的,一般若编码时指定码表为
utf-8,解码时指定码表为gbk,那么解码会出现汉字或其他乱码而不是?,如果反过来的情况一般大部分都是问号,具体
原理看下图:
2、ISO8859-1相关异常及解决办法
本程序的基本原理如下图
3、修改版UTF-8注意点
首先看一下修改版的编码规则:
修改版UTF-8在进行编码时,会参考表示头信息进行字节数的控制,就像上图所示,当读取到一个字节的首位为0,则这个字节单独表示一个字符;当读取的字节以110开头,如果是就以两个字节表示一个字符,且第二个字符一10开头;同理,当读取的字节以1110开头时,就会用三个字节表示一个字符,且后两个字节都是以10开头。一个很特殊的案例就是"联想"用GBK编码以后的字节码为"11000001","10101010","11001101","10101000"这四个字节正好符合修改版UTF-8中用两个字节表示一个字符的规则,所以当当用记事本来保存"联想"以后再打开时,记事本就会查找修改版UTF-8的码表进行解码,所以会出现乱码。
一、编码解码&码表
1、常见的编码表:
ASCII:美国标准信息交换码---用一个字节的7位可以表示。
ISO8859-1:拉丁码表---欧洲码表用一个字节的8位表示,负数。
GB2312:中国的中文编码表---每个文字用两个字节表示,两个都是负数,且该码表兼容ASCII码表。
GBK:中国的中文编码表升级,融合了更多的中文文字符号---同上。
Unicode:国际标准码,融合了多种文字---所有文字都用两个字节来表示,Java语言使用的就是unicode
UTF-8:根据投标来确定是用一个、两个还是三个字节来表示一个字符。
2、编码与解码:
编码 字符串---->字节数组
解码 字节数组---->字符串
二、转换流与码表的融合
1、InputStreamReader:字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
OutputStreamWriter:字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
2、转换流工作原理:
public class TransitionStreamDemo { public static void main(String[] args){ OutputStreamWriter iswUtf = null; InputStreamReader isrUtf = null; try { //编码码表指定为utf-8 iswUtf = new OutputStreamWriter(new FileOutputStream("utf.txt"), "utf-8"); iswUtf.write("你好"); } catch (Exception e) { throw new RuntimeException("文件创建异常"); }finally{ try { if (iswUtf != null) iswUtf.close(); } catch (Exception e2) { throw new RuntimeException("关闭输出流异常"); } } char[] buf = new char[3]; int len = 0; try { //解码码表指定为utf-8 isrUtf = new InputStreamReader(new FileInputStream("utf.txt"), "utf-8"); len = isrUtf.read(buf); System.out.println(new String(buf, 0, len)); } catch (Exception e) { throw new RuntimeException("文件读取异常"); }finally{ try { if (isrUtf != null) isrUtf.close(); } catch (Exception e2) { throw new RuntimeException("关闭输入流异常"); } } } }
程序执行流程按下图①-⑤所示的顺序进行:
三、乱码异常分析
1、UTF-8&GBK相关异常
public class CodingEncoding { public static void main(String[] args) throws IOException { OutputStreamWriter iswUtf = //指定编码码表为utf-8 new OutputStreamWriter(new FileOutputStream("utf.txt"),"utf-8"); OutputStreamWriter iswGbk = //指定编码码表为gbk new OutputStreamWriter(new FileOutputStream("gbk.txt"),"gbk"); iswUtf.write("你好"); iswUtf.close(); iswGbk.write("你好"); iswGbk.close(); char[] buf = new char[3]; int len = 0; InputStreamReader isrUtf = //编码时指定码表为utf-8,解码时指定码表为gbk new InputStreamReader(new FileInputStream("utf.txt"),"gbk"); InputStreamReader isrGbk = //编码时指定码表为gbk,解码时指定码表为utf-8 new InputStreamReader(new FileInputStream("gbk.txt"),"utf-8"); len = isrUtf.read(buf); isrUtf.close(); System.out.println(new String(buf,0,len)); len = isrGbk.read(buf); isrGbk.close(); System.out.println(new String(buf,0,len)); } }
本程序运行结果如下:
这种情况的其实就是编码码表与解码码表的不一致性引起的,而且这中间也是有规律可循的,一般若编码时指定码表为
utf-8,解码时指定码表为gbk,那么解码会出现汉字或其他乱码而不是?,如果反过来的情况一般大部分都是问号,具体
原理看下图:
2、ISO8859-1相关异常及解决办法
public class StringCoding { public static void main(String[] args) throws Exception{ String str = "你好"; //使用GBK字符集来对字符串进行编码 byte[] GBKByte = str.getBytes("GBK"); System.out.println(Arrays.toString(GBKByte));//打印结果:[-60, -29, -70, -61] String ISOString = new String(GBKByte,"ISO8859-1"); System.out.println(ISOString);//打印结果:全是?,且个数为4 //使用ISO8859-1字符集进行重新编码 byte[] ISOByte = ISOString.getBytes("ISO8859-1"); System.out.println(Arrays.toString(ISOByte));//打印结果:[-60, -29, -70, -61] //使用GBK字符集解码 String GBKString = new String(ISOByte,"GBK"); System.out.println(GBKString);//打印结果:你好 } }
本程序的基本原理如下图
3、修改版UTF-8注意点
首先看一下修改版的编码规则:
修改版UTF-8在进行编码时,会参考表示头信息进行字节数的控制,就像上图所示,当读取到一个字节的首位为0,则这个字节单独表示一个字符;当读取的字节以110开头,如果是就以两个字节表示一个字符,且第二个字符一10开头;同理,当读取的字节以1110开头时,就会用三个字节表示一个字符,且后两个字节都是以10开头。一个很特殊的案例就是"联想"用GBK编码以后的字节码为"11000001","10101010","11001101","10101000"这四个字节正好符合修改版UTF-8中用两个字节表示一个字符的规则,所以当当用记事本来保存"联想"以后再打开时,记事本就会查找修改版UTF-8的码表进行解码,所以会出现乱码。
相关文章推荐
- 黑马程序员_java基础篇操作数据的,操作字节数组的,字符编码Day6
- 黑马程序员——Java基础——对象序列化、管道流、RandomAccessFile类、操作基本数据类型的流对象、字符编码
- 黑马程序员---Java基础篇之常量、变量及运算符
- 黑马程序员java基础篇----网络编程总结
- 黑马程序员java基础篇----集合总结
- 黑马程序员—【Java基础篇】之IO流(二)———File类、递归、IO其它流和编码表
- 黑马程序员—【Java基础篇】之网络编程
- 黑马程序员java基础篇----多线程总结(下)
- 黑马程序员—【Java基础篇】之多态、内部类、异常及包
- 黑马程序员:轻松精通Java学习路线连载1-基础篇!
- 黑马程序员—基础篇之java环境搭建
- 黑马程序员—基础篇之初识java语法补充
- 黑马程序员_Java基础篇(四)——内部类总结
- 黑马程序员-JAVA学习第7课-字符编码的操作
- 黑马程序员:轻松精通Java学习路线连载1-基础篇!
- 黑马程序员_Java基础篇(三)——抽象类和接口的对比
- 黑马程序员—【Java基础篇】之面向对象
- 黑马程序员java基础篇----关于java内存分配
- 黑马程序员 JAVA基础篇(一)
- 黑马程序员-java基础篇