GBK/GB2312编码问题分析以及java获取汉字国标码

编码问题分析

个人经验:

  这几天在公司,发报文调试接口的时候由于使用UTF8跟GBK两种编码很头疼。页面显示为utf8码,但是解析报文使用的却是GBK,这样就会出现两种情况,要么你调试页面是正常的,报文是乱的,要么调试页面使用乱码格式,报文显示正常!。。。。总结后:发现一个项目中必须要统一使用一种编码格式!然后就是不同编码必定会有差异,GBK编码跟utf8编码是不可能存在转换关系的,用什么样的编码格式发送的就需要使用该格式去解析!

GBK/GB2312透析:

  

import java.io.UnsupportedEncodingException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class GBKEncodeUtil {
	/**
	 * GB2312/GBK编码类
	 * 
	 * 机内码,区位码,国标码  三者间存在联系,由于机内码,国标码一般以四位十六进制的形式存在,区位码以四位十进制表示。
	 * 
	 * 举例子: 
	 *   德  ---区位码:2134
	 *  机内码:  高位字节 = 21(十进制) + A0H(十六进制) = 15H + A0H = B5H
	 *          低位字节 = 34(十进制) + A0H(十六进制) = 22H + A0H = C2H    
	 *           机内码: B5C2H
	 *  国标码:  高位字节 = 21(十进制) + 20H(十六进制) = 15H + 20H = 35H
	 *          低位字节 = 34(十进制) + 20H(十六进制) = 22H + 20H = 42H
	 *           国标码: 3542H  
	 *           
	 *           同理: 国标码 = 机内码 - 8080H
	 */
    public static void main(String[] args) {
    	String str = "德".trim();
    	System.out.println(str);
    	System.out.println("机内码:0x" + getJineiMa(str));
    	System.out.println("区位码:" + getLocationCode(str));
    	System.out.println("国标码:0x" + getGBCode(str));
    	System.out.println(getCharacter("B0A1"));
    	
	}
    
    /**
	 * 判断str是否为汉字
	 * @param str 待检测值
	 * @return true 是 false 不是
	 */
	public static boolean isCharacter(String str){
		  Pattern p_str = Pattern.compile("[\\u4e00-\\u9fa5]+");
		  Matcher m = p_str.matcher(str);
		  if(m.find()&&m.group(0).equals(str)){
			  return true;
		  }
		  return false;
	}
	/**
	 * 获取机内码
	 * @param chineseName
	 * @return 汉字的机内码  String类型
 	 */
	public static String getJineiMa(String chineseName){
		StringBuffer sb = new StringBuffer();
		try {
			char[]ch = chineseName.toCharArray();
			for (char c : ch){
				if (isCharacter(String.valueOf(c))){
					byte[]by = String.valueOf(c).getBytes("GBK");
					for (byte b : by){
						sb.append(Integer.toHexString(b & 0xff));
					}
				}else{
					byte b = (byte) c;
					sb.append(Integer.toHexString(b & 0xff));
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return sb.toString().toUpperCase().trim();
	}

	/**
	 * 获得汉字区位码
	 * 
	 * @param chineseName 汉字
	 *            
	 * @return 单个汉字区位码
	 */
	public static String getLocationCode(String chineseName){
		// 先判断chinese是否为汉字
		if (!isCharacter(chineseName)) return "输入的不是汉字!";
		String jiNeiMa = getJineiMa(chineseName);
		String highOrder = jiNeiMa.substring(0, 2);  // 高位
		String lowOrder = jiNeiMa.substring(2, 4);   // 低位
		String quWeiMa = String.valueOf((Integer.parseInt(highOrder, 16) - 0xA0)) + String.valueOf(Integer.parseInt(lowOrder, 16) - 0xA0);
		return quWeiMa;
	}
	/**
	 * 获取  国标码
	 * @param chineseName
	 * @return
	 */
    public static String getGBCode(String chineseName){
    	// 先判断chinese是否为汉字
    	if (!isCharacter(chineseName)) return "输入的不是汉字!";
    	int jiNeiMa = Integer.parseInt(getJineiMa(chineseName), 16);
    	String gbMa = Integer.toHexString(jiNeiMa - 0x8080);
    	return gbMa;
    }
    
    /**
          根据机内码获取汉字
	 * @param quWeiMa
	 * @return 汉字
     */
    public static String getCharacter(String jiNeiMa){
    	byte b1 = (byte) Integer.parseInt(jiNeiMa.substring(0, 2), 16);
    	byte b2 = (byte) Integer.parseInt(jiNeiMa.substring(2, 4), 16);
    	
    	String str = null;
		try {
			str = new String(new byte[]{b1,b2}, "GBK");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
    	return str;
    }
    
}

运行结果:

德
机内码:0xB5C2
区位码:2134
国标码:0x3542
啊



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值