主要的几种编码方式:
Java中字符的编码:
同一种 编码格式,字节流的存储方式也可能不一样,例如UTF-8是一种变长字节编码方式
编码格式:
查看当前系统的默认编码方式,一般为GBK
System.getProperty("file.encoding")
枚举所有可用编码方式
Map<String,Charset> map=Charset.availableCharsets();
for(Map.Entry<String,Charset> entry:map){
entry.getKey();
}
与字符串有关方法的解析:
String string="阿";
/*字符串到字节流*/
byte[] bytesDefault=string.getBytes(); //以该编码方式把字符串以系统默认编码的方式解析成字节流。
byte[] bytesUTF8=string.getBytes("UTF-8"); //以指定的UTF-8编码方式把字符串解析成字节流
/*字节流到字符串*/
String newString=new String(bytesDefault,"UTF-8"); //将所给的字符流以UTF-8的方式编码为字符串
/*字符到索引*/
int index=(int)string.charAt(0); //指定位置字符在系统默认编码方式下的索引
String hexIndex=Integer.toHexString(index); //数的十六进制表示
/*索引到字符*/
String charStr=String.valueOf((char)index); //系统默认编码方式中该索引对应的字符
/*字符串到字节流*/
//字符串以3字节UTF-8形式存储时的字节流形式
/*字节流到字符串*/
"%E9%B8%BF"
"; //示例
//3字节UTF-8字节流转化为字符串
索引到字节流可以用类似URLDecoder的类来解决,也可以自己写代码以其他方式,例如转化为6字节UTF-8字节流。
这时可能还需要写一段字节流到索引的方法,因为 如果要以转化成3字节以外的UTF8字节流方式存储,是可以以UTF8的方式正常解码,却无法用URLDecoder得到索引。
下面是一段字符索引到字符串的代码,可以用数字表示单个索引,也可以固定的utf-8编码格式表示多个索引
private static final Pattern unicodeReg=Pattern.compile("[0-9A-Fa-f]{4}");
//3Bytes
public static String UTF8ToString(int code) throws UnsupportedEncodingException{
byte[] strbyte=new byte[4];
strbyte[0]=(byte) ((code>>12&0x000F)|0x00E0);//1110XXXX
strbyte[1]=(byte) ((code>>6&0x003F)|0x00B0);//10XXXXXX
strbyte[2]=(byte) ((code&0x003F)|0x00B0);//10XXXXXX
return new String(strbyte,"UTF-8");
}
//3Bytes
public static String UTF8ToString(String code) throws UnsupportedEncodingException{
byte[] strbyte=new byte[4*(code.length()/6)];
for(int i=0;i<code.length();i++){
if('\\'==code.charAt(i)&&'u'==code.charAt(i+1)){
Matcher matcher=unicodeReg.matcher(code.substring(i+2,i+6));
if(matcher.find()){
int strcode=Integer.parseInt(code.substring(i+2,i+6),16);
strbyte[i*4]=(byte) ((strcode>>12&0x000F)|0x00E0);//1110XXXX
strbyte[i*4+1]=(byte) ((strcode>>6&0x003F)|0x00B0);//10XXXXXX
strbyte[i*4+2]=(byte) ((strcode&0x003F)|0x00B0);//10XXXXXX
i+=6;
}
}
}
String result;
result=new String(strbyte,"UTF-8");
return result;
}
PS:测试的时候不要写错成unicode的转义字符,用\\uXXXX\\uXXXX\\uXXXX的形式测试,下面是Java中所有转义字符
在使用百度搜索的时候,其实可以直接实现字符串到3字节UTF8字节流的转换,搜索任意中文字符,地址栏中的word参数值就是字节流(Chrome貌似做了转换,把全部地址 复制出来就可以了,IE可以看到)。
比如搜索“二叉树”,地址内容是
https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=0&rsv_idx=1&tn=baidu&wd=%E4%BA%8C%E5%8F%89%E6%A0%91&rsv_pq=fb32fec60000d348&rsv_t=d701K52XrcHEiBAg14OTk%2F1%2FxAPPGvBMUsdV8IesAtsUAGTJbTE4zvtW5MM&rsv_enter=1&rsv_sug3=5&rsv_sug1=4&rsv_pq=fb32fec60000d348&rsv_t=d701K52XrcHEiBAg14OTk%2F1%2FxAPPGvBMUsdV8IesAtsUAGTJbTE4zvtW5MM&rsv_enter=1&rsv_sug3=5&rsv_sug1=4
%E4%BA%8C%E5%8F%89%E6%A0%91就是我们要的字节流。
这里一个小插曲,如果UTF-8编码方式被错误解析成GBK(GB2312)编码格式,会出现什么字符呢?
只要把ie=utf-8改成ie=ISO8859就可以看到了,被错误解析的字符会比原来多1/3个。
因为我的系统默认编码就是GBK,所以猜测在客户端有这样的机制,即 当指定查询字节流时,网页会认为查询的是中文字符串,如果没有指定正确的中文字符集,客户端自动指定默认编码格式为GBK,并将其与查询的字节流一并发送到服务器,服务器即以所指定的GBK编码格式解析成中文,进行查询并返回结果。
这里还要PS一下,这里的GBK编码和网络上查询相应字符得到的GBK编码不一样,因为这里的GBK编码是已经按固定格式(例如UTF8的3字符格式)转换好的,具体转换原理还要研究一下。比如说我在Nodepad里输入这么一串字符串
E4BA8CE58F89E6A091,HexToASCII后,在GB2312编码下是浜屽弶鏍?,而实际上E4BA在网上查不到对应的GBK编码(似乎9FB3是最后一个),GBK编码的生成方式暂时还要研究一下~