Java应用开发中的字符集与字符编码

时间:2023-12-13 15:25:50

事出有因

在向HttpURLConnection的输出流写入内容时,因没有设置charset,导致接收方对数据的验签不一致。

URL url = new URL(requestUrl);
//打开连接
HttpURLConnection urlConn = (HttpURLConnection)url.openConnection(); ......
...... //获取输出流
out = new OutputStreamWriter(urlConn.getOutputStream());
//发送请求参数
out.write(concatKeyValue(params, false));
out.flush()

回过头来看,问题看似挺容易解决,只需在获取输出流时,指定字符编码集

out = new OutputStreamWriter(urlConn.getOutputStream(), "utf-8");

但实则费了一番工夫。期间心里产生了过以下的问题:

1、String.getBytes(String charset)与String(Byte[] bytes, String charset)的使用。

2、什么场合下会涉及的字符编码的转换呢?

3、在不显示指定charset时,java使用Charset.defaultCharset()来获取默认字符编码。Charset.defaultCharset()的值来自哪里?

为了在以后的开发中,快速解决字符集相关问题。在这里对字符集做了一次比较系统的学习。

字符集与字符编码

字符是各种文字与符号的总称,比如语言符号、图形符号、标点。

字符集是字符的集合,每个字符集包含的字符个数不同,常见的字符集有:unicode字符集、ISO 8859字符集、GB2312字符集、GB18030字符集、BIG5字符集等。

字符编码是以二进制数字来对应字符集中的字符,使得计算机能够识别字符集中的字符。

各个国家在制定编码标准的时候,通常是同时制定字符集与编码规范。因此常见的字符集,如GB2312,除了表示“字符集”这一层含义外,也包含了编码的含义。

Unicode字符集有多种编码方式,如UTF-8、UTF-16等;ASCII只有一种;大多数MBCS(Multi-Byte Chactacter System,即多字节字符系统)(包括GB2312)也只有一种。

Java

Java中的字节码文件始终以unicode编码方式保存。Java运行时创建的字符串变量、常量等字符串均以unicode编码存储在内存中。

当涉及数据读写时,就会涉及字符的编码转换问题,例如从磁盘读取文件时、向磁盘写入文件时、接收网络发送来的数据时等。

数据存储到物理介质或通过物理介质传输时,都是以bit流的形态存在。而要传输正确的bit流,就需要声明和设置恰当的字符编码。

getBytes()与getBytes(charset)

当不指定字符集时,getBytes内部会获取当前操作系统的默认字符集。

getBytes获得字符串的指定编码规范对应的字节数组,此过程称为编码。

//s的字符编码方式为unicode(utf-16), jvm的默认编码规则
String s = "我们";
//得到s的gbk编码, unicode(utf-16) --> gbk
byte[] bytes = s.getBytes("gbk");

String的构造函数String(byte[] bytes, String charset)

//解码,gbk --> unicode(utf-16)
String p = new String(bytes, "gbk");

Charset.defaultCharset()

此方式用来获取默认字符集,默认字符集在jvm启动时已经根据系统环境确认,不可以修改(或者说修改并不会生效)。当jvm的启动时,也可以通过参数-Dfile.encoding指定字符集,或通过环境变量修改默认字符集。

另外也请注意我们运行main方法与web项目的不同,它们启动了jvm的不同实例,所以默认字符集可能不同。所以如果在main方法中打印Charset.defaultCharset().name()的值 与实际运行web项目时输入的值不同,也不要觉得奇怪。

但凡涉及中文(web开发、I/O、数据库读写等),乱码问题会与我们不期而遇,所以理解字符集和字符编码就很有必要。

另外:

当我们使用IDE(idea/eclipse)时,我们可以设置开发环境所使用字符集。请注意:IDE中设置的字符集只能代表IDE在存取源代码文件时使用了何种字符集,而不是class文件使用了何种字符集。

好文推荐:《java中文乱码解决之道(五)—–java是如何编码解码的》