java编码问题,GBK转化为UTF-8

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java编码问题,GBK转化为UTF-8相关的知识,希望对你有一定的参考价值。

问题是这样的,向接口发送了一个请求,接口返回一串字符串S 这个字符串编码格式为utf-8
我系统中使用的编码格式为GBK,导致出错。
s=new String(s.getBytes("gbk"),"utf-8");
这样处理完以后,字符串S中,部分编码正确,部分编码不正确
中华人民共和??213123
正常应该是中华人民共和国1213123
具体怎么解决呢
换成大写的GBK跟UTF-8还是不行。。。哎。

首先理解java的字符概念
java中字符串是字符的序列,虚拟机内部的字符都是16位的unicode字符,等价于C++中的WCHAR,也是为了实现虚拟机方便

WCHAR叫做宽字符,对应的MuitiChar叫做多字符,这种多字符中字符的位数不唯一

GBK 和 UTF8 是多字符的不同编码形式

s=new String(s.getBytes("gbk"),"utf-8");
的意思是:
byte[] bytes=s.getBytes("gbk");
s=new String(bytes,"utf-8");

第一句是将s对应的gbk编码转出来,形成一个字节流
第二句是将这个字节流按照utf-8编码转为java字符串,因此相当于将gbk编码的字节流当做utf-8来使用,这样在中文中会出现乱码

你的问题是,接口返回的已经是utf-8 所以它必须是byte[] 流,如果是字符串的话就不好办了
参考技术A 乱码问题不能只丛编码转化来解决,要从根源上解决! 一般都是用UTF-8编码!大致要分为3个步骤:
1:页面上要指定编码格式: <%@ page language = "java" contentTpye = "text/html; charset = UTF-8" pageEncoding = "UTF-8" %>
2: 工作空间指定编码格式 :WINDOWS --〉首选项 (pREFERENCES)--> General --->workspace 下 有一个 Text file encodeing 的区块 默认的是 GB18030 要选择other 值为 UTF-8; 旁边的 new text file line delimiter 也可以设置 选择other 值为 UTF-8,最好是默认Default.
3: 数据库的编码格式 最好也设置成UTF-8! 具体操作可询问dba ,或者上网查资料。
参考技术B s是utf-8格式的,你用s.getBytes("gbk")就存在问题,有的不能转过来,所以你该这样s=new String(s.getBytes(),"utf-8");或s=new String(s.getBytes("utf-8"));这样就对了,这样得到的是正确的UTF-8,如果要最终转换成GBK,s=new String(s.getBytes("utf-8"), “gbk”);就可以啦 参考技术C 我理解是你写反了:
s=new String(s.getBytes("utf-8"),"gbk");

还有就是,请检查你直接用GBK格式输出看看对端给你的是否正确。也就是说先判断来源是否OK,再判断处理的是否OK
参考技术D

这个问题我之前回答过:http://zhidao.baidu.com/question/1301912846509946579.html?oldq=1

s=new String(s.getBytes("gbk"),"utf-8");

这种写法是错误的,要么

s=new String(s.getBytes("gbk"),"gbk");

要么

s=new String(s.getBytes("utf-8"),"utf-8");

另外请确认s原来的编码到底是什么是gbk,还是uft-8,如果原来s可以正常输出的话(应该不可能,不然就不会转码了),那就直接采用上面两种做法就可以了

Java字符编码的转化问题

概述:

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

  问题是这种,我们通过二维码扫描来获得二维码中的信息。可是。我们的二维码的产生过程却是“多样化”的。即在产生二维码的时候是以不同的字符串编码类型进行编码的。比方,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的转化,是能够转换回来的。例如以下測试:

  技术分享

  结果:

  技术分享





































以上是关于java编码问题,GBK转化为UTF-8的主要内容,如果未能解决你的问题,请参考以下文章

Java工程编码格式由GBK转化成utf-8(编码格式互转)

Java字符编码的转化问题

HTML编码UTF-8转为GBK

如何将gbk 编码的字符串转换成 utf

Java 中文字符串编码之GBK转UTF-8

java 将编码格式为utf-8的文件内容以 GBK编码存到txt文档