博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java字符编码的转化问题
阅读量:6705 次
发布时间:2019-06-25

本文共 4452 字,大约阅读时间需要 14 分钟。

概述:

  我想字符串的编码问题的确会困扰到非常多开发人员。我近期也是被困扰到了。

  问题是这种,我们通过二维码扫描来获得二维码中的信息。可是。我们的二维码的产生过程却是“多样化”的。即在产生二维码的时候是以不同的字符串编码类型进行编码的。比方,GBK、GB2312、UTF-8等等。而这些不同的编码类型会产生不同的字节。在Java中。GBK和GB2312都是1个汉字占2个字节,UTF-8是1个汉字占3个字节。而ISO编码则是1上汉字1个字节。这样一来,我们在扫描二维码的时候就会出现一些“阴阳怪气”的乱码字符。

  这里我们是开发二维的扫描。而二维码的生成则在来自不同的产商。

我的前期实验:

  系统字符格式:UTF-8

  字符串"中国"的GB2312编码字节数组bs_gb和UTF-8编码字节数组bs_utf
    byte[] bs_gb = {-42, -48, -71, -6};
    byte[] bs_utf = {-28, -72, -83, -27, -101, -67};

  实验步骤:

    1.首先对bs_gb分别使用GB2312编码和UTF-8编码转化为一个中间结果:

      String gbStr1 = new String(bs_gb, "GB2312");
      String utfStr1 = new String(bs_gb, "UTF-8");
      结果:
      中国
      ?й?

    2.对utfStr1进行GB2312编码,实现从 GB2312编码 -> UTF-8编码 -> GB2312编码 的过程
      String gbStr2 = new String(utfStr1.getBytes("UTF-8"), "GB2312");
      结果:锟叫癸拷
  
    3.对bs_utf分别使用GB2312编码和UTF-8编码转化为一个中间结果:
      String gbStr3 = new String(bs_utf, "GB2312");
      String utfStr2 = new String(bs_utf, "UTF-8");
      结果:
      涓??

      中国
  
    4.对gbStr3进行UTF-8编码,实现从 UTF-8编码 -> GB2312编码 -> UTF-8编码 的过程
      String utfStr3 = new String(gbStr3.getBytes("GB2312"), "UTF-8");
      结果:
      ??

?

  
    5.根据上面4个步骤。进行GBK和UTF-8之间的转换实验
    实验的初步结论

      UTF-8编码和GB2312编码之间不能进行直接转化

      UTF-8编码和GBK编码之间,仅仅能是UTF-8 -> GBK -> UTF-8

不同编码字符之间的转化:

  UTF-8转化为Unicode

private static final char[] hexDigit = {		'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'	};	    private static char toHex(int nibble) {		return hexDigit[(nibble & 0xF)];	}		/**     * 将字符串编码成 Unicode。     * @param theString 待转换成Unicode编码的字符串。

* @param escapeSpace 是否忽略空格 * @return 返回转换后Unicode编码的字符串。

*/ public static String toUnicode(String theString, boolean escapeSpace) { int len = theString.length(); int bufLen = len * 2; if (bufLen < 0) { bufLen = Integer.MAX_VALUE; } StringBuffer outBuffer = new StringBuffer(bufLen); for(int x=0; x<len; x++) { char aChar = theString.charAt(x); // Handle common case first, selecting largest block that // avoids the specials below if ((aChar > 61) && (aChar < 127)) { if (aChar == '\\') { outBuffer.append('\\'); outBuffer.append('\\'); continue; } outBuffer.append(aChar); continue; } switch(aChar) { case ' ': if (x == 0 || escapeSpace) outBuffer.append('\\'); outBuffer.append(' '); break; case '\t': outBuffer.append('\\'); outBuffer.append('t'); break; case '\n': outBuffer.append('\\'); outBuffer.append('n'); break; case '\r': outBuffer.append('\\'); outBuffer.append('r'); break; case '\f': outBuffer.append('\\'); outBuffer.append('f'); break; case '=': // Fall through case ':': // Fall through case '#': // Fall through case '!': outBuffer.append('\\'); outBuffer.append(aChar); break; default: if ((aChar < 0x0020) || (aChar > 0x007e)) { outBuffer.append('\\'); outBuffer.append('u'); outBuffer.append(toHex((aChar >> 12) & 0xF)); outBuffer.append(toHex((aChar >> 8) & 0xF)); outBuffer.append(toHex((aChar >> 4) & 0xF)); outBuffer.append(toHex( aChar & 0xF)); } else { outBuffer.append(aChar); } } } return outBuffer.toString(); }

  Unicode转化为UTF-8

/**	 * unicode 转换成 utf-8	 * 	 * @param theString	 * @return	 */	public static String unicodeToUtf8(String theString) {		char aChar;		int len = theString.length();		StringBuffer outBuffer = new StringBuffer(len);		for (int x = 0; x < len;) {			aChar = theString.charAt(x++);			if (aChar == '\\') {				aChar = theString.charAt(x++);				if (aChar == 'u') {					// Read the xxxx					int value = 0;					for (int i = 0; i < 4; i++) {						aChar = theString.charAt(x++);						switch (aChar) {						case '0':						case '1':						case '2':						case '3':						case '4':						case '5':						case '6':						case '7':						case '8':						case '9':							value = (value << 4) + aChar - '0';							break;						case 'a':						case 'b':						case 'c':						case 'd':						case 'e':						case 'f':							value = (value << 4) + 10 + aChar - 'a';							break;						case 'A':						case 'B':						case 'C':						case 'D':						case 'E':						case 'F':							value = (value << 4) + 10 + aChar - 'A';							break;						default:							throw new IllegalArgumentException(									"Malformed   \\uxxxx   encoding.");						}					}					outBuffer.append((char) value);				} else {					if (aChar == 't')						aChar = '\t';					else if (aChar == 'r')						aChar = '\r';					else if (aChar == 'n')						aChar = '\n';					else if (aChar == 'f')						aChar = '\f';					outBuffer.append(aChar);				}			} else				outBuffer.append(aChar);		}		return outBuffer.toString();	}

  而对于其GB2312的编码格式是不能够在获得一个字符串之后再转化成其它的编码格式的。

比方,我的一个字符串为“中国”,我把它转成GB2312的编码格式为:涓��,再转成UTF-8就变成了�?

?

  只是还好,对于经过GBK和ISO-8859-1这两种格式编码之后的字符,再进行UTF-8的转化,是能够转换回来的。例如以下測试:

  

  结果:

  

你可能感兴趣的文章
awstats安装配置
查看>>
排序算法---希尔排序
查看>>
mysql 无法启动 Can't find file: './mysql/plugin.frm'
查看>>
oracle10g linux手工建库
查看>>
tcpdump抓取oracle报文以及使用Wireshark分析
查看>>
thinkphp http类的应用
查看>>
oKit-解决运营过程中产生的大数据图片造成的困扰
查看>>
cocos2d-x 22种特效
查看>>
时间与爱
查看>>
解决chrome下文字大小不能小于12px的bug
查看>>
第1章:sed语法和基本命令(1)
查看>>
TCP連接狀態及三次握手四次揮手
查看>>
Linux常用命令汇总
查看>>
实现自定义的actuator端点
查看>>
爱情,是一场狡猾的战斗!
查看>>
rabbitmq在redhat5.5下搭建部署
查看>>
10.8.2,ssd开启trim
查看>>
Mac os X 必备的System Info 最新版
查看>>
配置管理小报100208:如何在不覆盖本地文件的情况下,获取文件的某个历史版本...
查看>>
android:name 的秘密
查看>>