黑马程序员---字符编码

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

 

转换流的字符编码:


字符流的出现为了方便操作字符。

更重要是的加入了编码转换。

通过子类转换流来完成。
InputStreamReader
OutputStreamWriter

还有两个能加入字符集的是:PrintStream & PrintWriter 它们两个只能打印,不能读取。

所以玩编码表还是以转化流为主。

在两个对象进行构造的时候可以加入字符集。

 

编码表的由来
计算机只能识别二进制数据,早期由来是电信号。
为了方便应用计算机,让它可以识别各个国家的文字。
就将各个国家的文字用数字来表示,并一一对应,形成一张表。
这就是编码表。

 

常见的编码表


ASCII:美国标准信息交换码。
用一个字节的7位可以表示。

ISO8859-1:拉丁码表。欧洲码表。(拉丁语系,意大利语,法语)
用一个字节的8位表示。最高位置1.


GB2312:中国的中文编码表。两个字节一个汉字。兼容ASCII,为了和ASCII不冲突,两个字节最高位都置1。汉字都是负数。
GBK:中国的中文编码表升级,融合了更多的中文文字符号。(要么这种)


Unicode:国际标准码,融合了多种文字。
所有文字都用两个字节来表示,Java语言使用的就是unicode,char型


UTF-8:最多用三个字节来表示一个字符。(做项目,要么这种)
......

 

 

转换流的编码应用
可以将字符以指定编码格式存储。
可以对文本数据指定编码格式来解读。
指定编码表的动作由构造函数完成。

import java.io.*;
class EncodeStream 
{
	public static void main(String[] args) throws IOException
	{
		//writeFile();
		readFile();
	}

	public static void readFile()throws IOException
	{
		InputStreamReader isr = new InputStreamReader(new FileInputStream("UTF.txt"),"UTF-8");

		char[] ch  = new char[10];
		int len = 0;
		len=isr.read(ch);
		String s = new String(ch,0,len);

		System.out.println(s);
	}

	public static void writeFile()throws IOException
	{
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("UTF.txt"),"UTF-8");
		osw.write("你好");
		osw.close();
	}
}


 

字符编码


编码:字符串 --> 字节数组

字符串中:字符串 变 字节数组 的方法

 byte[]getBytes()
          使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
 byte[]getBytes(Charset charset)
          使用给定的 charset 将此String 编码到 byte 序列,并将结果存储到新的 byte 数组。

 byte[]getBytes(String charsetName) throwsUnsupportedEncodingException
          使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
如果指定的字符集不受支持 - UnsupportedEncodingException

解码:字节数组 --> 字符串

使用字符串的构造方法就可以使 字节数组 变成 字符串。

构造方法摘要
String(byte[] bytes, String charsetName)  throws UnsupportedEncodingException
          通过使用指定的 charset 解码指定的 byte 数组,构造一个新的String

如果指定的字符集不受支持 - UnsupportedEncodingException

String(byte[] bytes)
          通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String
String(byte[] bytes, Charset charset)
          通过使用指定的 charset 解码指定的 byte 数组,构造一个新的String

 

将 数组中的内容 变成 字符串形式 (打印查看):

java.util  类 Arrays

static StringtoString(boolean[] a)
          返回指定数组内容的字符串表示形式。
static StringtoString(byte[] a)
          返回指定数组内容的字符串表示形式。
static StringtoString(char[] a)
          返回指定数组内容的字符串表示形式。
static StringtoString(double[] a)
          返回指定数组内容的字符串表示形式。
static StringtoString(float[] a)
          返回指定数组内容的字符串表示形式。
static StringtoString(int[] a)
          返回指定数组内容的字符串表示形式。
static StringtoString(long[] a)
          返回指定数组内容的字符串表示形式。
static StringtoString(Object[] a)
          返回指定数组内容的字符串表示形式。
static StringtoString(short[] a)
          返回指定数组内容的字符串表示形式。

import java.util.*;
class EncodeDemo 
{
	public static void main(String[] args) throws Exception
	{
		String s = "你好";

		byte[] by = s.getBytes("GBK");//编码

		System.out.println(Arrays.toString(by));//[-60, -29, -70, -61]

		String s1 = new String(by,"GBK");//解码

		System.out.println(s1);//你好
	}
}


编码的时候指定了GBK,解码的时候指定成了欧洲码表ISO8859-1,可以再用错的编码表编码一次,然后再用对的码表解码就行。

(服务器那边一般使用ISO8859-1,所以这方法通用)

import java.util.*;
class EncodeDemo 
{
	public static void main(String[] args) throws Exception
	{
		String s = "你好";

		byte[] by = s.getBytes("GBK");//编码表不能指定错了,如果指定成欧洲编码表就完了

		System.out.println(Arrays.toString(by));//[-60, -29, -70, -61]

		String s1 = new String(by,"ISO8859-1");//解码的时候指定错了,指定成了欧洲码表

		System.out.println(s1);//????

		//解决方案:可以再用错的编码表编码一次,然后再用对的码表解码就行
		byte[] by1 = s1.getBytes("ISO8859-1");

		System.out.println(Arrays.toString(by1));//[-60, -29, -70, -61]

		String s2 = new String(by1,"GBK");

		System.out.println(s2);//你好
	}
}


 

编码的时候指定了GBK,解码指定了UTF-8,用编一次解一次是变不回去的。

import java.util.*;
class EncodeDemo 
{
	public static void main(String[] args) throws Exception
	{
		String s = "你好";

		byte[] by = s.getBytes("GBK");//编码表不能指定错了,如果指定成欧洲编码表就完了

		System.out.println(Arrays.toString(by));//[-60, -29, -70, -61]

		String s1 = new String(by,"UTF-8");//编码的时候指定了GBK,解码指定成了UTF-8

		System.out.println(s1);//???

		//编码的时候指定了GBK,解码指定了UTF-8,用编一次解一次是变不回去的。
		byte[] by1 = s1.getBytes("UTF-8");

		System.out.println(Arrays.toString(by1));//[-17, -65, -67, -17, -65, -67, -17, -65, -67]

		String s2 = new String(by1,"GBK");

		System.out.println(s2);//锟斤拷锟?
	}
}
import java.util.*;
class EncodeDemo 
{
	public static void main(String[] args) throws Exception
	{
		String s = "哈哈";

		byte[] by = s.getBytes("GBK");//编码表不能指定错了,如果指定成欧洲编码表就完了

		System.out.println(Arrays.toString(by));//[-71, -2, -71, -2]

		String s1 = new String(by,"UTF-8");//编码的时候指定了GBK,解码指定成了UTF-8

		System.out.println(s1);//????

		//编码的时候指定了GBK,解码指定了UTF-8,用编一次解一次是变不回去的。
		byte[] by1 = s1.getBytes("UTF-8");

		System.out.println(Arrays.toString(by1));//[-17, -65, -67, -17, -65, -67, -17, -65, -67, -17, -65, -67]

		String s2 = new String(by1,"GBK");

		System.out.println(s2);//锟斤拷锟斤拷
	}
}

造成这个错乱现象主要是因为GBK和UTF-8都支持中文造成的。

我们一般会接触到的码表是:GBK 和 UTF-8 和 ISO8859-1。



联通

保存,关闭,然后再打开:

 

 你存联通的时候默认是GBK的,这两个字符4字节写进去了,当你在双击打开记事本这个应用程序的时候,解码出现问题。

点击文件-另存为:

 弹出对话框:

 我们发现它已经识别成UTF-8的编码了。

 

现在我们说说GBK 和 UTF-8 有什么特点:

同样是汉字,怎么区分什么时候使用2个字节编码,什么时候使用3个字节。

java.io 接口 DataInput 中:


 

import java.util.*;
class EncodeDemo2 
{
	public static void main(String[] args) throws Exception
	{
		String s = "联通";

		byte[] by = s.getBytes("GBK");//编码

		for(byte b : by)
		{
			System.out.println(Integer.toBinaryString(b&255));//只取后8位
		}
	}
}


对照UTF-8

我们发现它的编码形式与UTF-8一致:高字节以110开头,低字节以10开头。  "110 . . . . ."   "10 . . . . . ."   "110 . . . . ."   "10 . . . . . ."

记事本在编码的时候发现这个编码规律跟UTF-8的一致,直接就去查UTF-8码表了。

就因为联通哦这三个字的编码规律非常符合UTF-8的规律,别的字没有。

  

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值