安卓中的乱码以及编码问题

 Android乱码以及编码转化

     To live is to function,that is all there is in living.

      乱码发火是安卓开发中常常遇到的事情,AndroidStudio默认的是UTF-8编码,而网站常用GBK(GB2312老版)编码,为了避免网络请求出现问题,常常会对网络接口中的的文字进行编码,也会对返回的数据进行编码,如何在UTF-8的环境下将汉字成功的转换成其他编码尼疑问,这是该篇博客为读者解答的事情微笑,读完此篇博客,你将对编码有新的认识,从此乱码与你是路人,编码不在是难事,此篇博客乃一家之言,若有问题请直言骂人以待校正吐舌头

    首先,介绍一下编码,解码的概念,以及为什么要编码   。

  编码:将源对象内容按照一种标准转换为一种标准格式内容。 
  解码:和编码对应的,它使用和编码相同的标准将编码内容还原为最初的对象内容。 
  编解码的目的最初是为了加密信息,经过加密的内容不知道编码标准的人很难识别,已经有数千年历史了。 
  而现在编解码种类非常多,主要目的则是为了信息交换。 
  除了加密,目前程序中常见的如字符编解码,HTML编解码,URL编解码,邮件编解码,多媒体编解码等。编码是为了符合传输的要求,解码是为了还原成我们能识别的信息。 
  例如字符编解码,字符编码在一系列数字与人们将文本输入到计算机中时希望看到的字符之间提供映射。因为世界上有不同的语言和文字,所以需要将不同的文字编码以通过计算机处理和传输。 
  再比如多媒体编解码,因为有多种不同格式的图像声音,所以它们各自有自己编解码标准。
   那么今天我们主要处理安卓中的文字编码解码问题,至于加密在后续文章我将会提到。

   介绍一个工具——站长工具之编码转换http://tool.chinaz.com/tools/utf-8.aspx 可以将经行多种编码之间的转换,当然站长工具还有其他功能,君可慢慢细看

        我需要的编码:

        已知晓的文字:动漫卡通

        后台需要的编码为:%25u52A8%25u6F2B%25u5361%25u901A

       接下来使用站长工具进行编码处理,如下图:

      一:直接使用UrlEncode


  可以看见其对应的编码是:%e5%8a%a8%e6%bc%ab%e5%8d%a1%e9%80%9a,这和我们的需求相差很远,那么如果再一次进行编码会不会达到我们的期望尼,接下来拭目以待:


   二次UrlEncode对应的编码是:%25e5%258a%25a8%25e6%25bc%25ab%25e5%258d%25a1%25e9%2580%259a,所以简单的

URLEncode.encode()方法并不能达到需求,那么怎么办尼

   接下来仍然使用站长工具,复制“动漫卡通”,测试其他编码是否能实现。。。终于在使用GBK——UTF-8的时候我看见了希望。


   待编码文字:动漫卡通      需得到的编码:%25u52A8%25u6F2B%25u5361%25u901A

   目前通过GBK转UTF-8可以达到:动漫卡通

   同志们有没有觉得革命已经胜利了尼!数字部分已经出来了,如果String.replace(“&#x”,“25u%”)来替换便可以实现目的,但是国内网站的中文环境是多数是GBK(GBK2312),而studio的环境默认的是utf-8,如何在UTF-8的环境下实现这一转变尼?

   接下来我们需要了解一个新的知识:Uniconde编码。

  什么是Unicode编码尼?请看下图(来源于百度百科)

   

  

     Unicode 是为了解决传统的字符编码方案的局限而产生的,例如ISO 8859所定义的字符虽然在不同的国家中广泛地使用,可是在不同国家间却经常出现不兼容的情况。很多传统的编码方式都有一个共同的问题,即容许电脑处理双语环境(通常使用拉丁字母以及其本地语言),但却无法同时支持多语言环境(指可同时处理多种语言混合的情况)。
    Unicode 编码包含了不同写法的字,如“ɑ/a”、“户/户/戸”。然而在汉字方面引起了一字多形的认定争议(详见中日韩统一表意文字主题)。
    在文字处理方面,统一码为每一个字符而非字形定义唯一的代码(即一个整数)。换句话说,统一码以一种抽象的方式(即数字)来处理字符,并将视觉上的演绎工作(例如字体大小、外观形状、字体形态、文体等)留给其他软件来处理,例如网页浏览器或是文字处理器。
    几乎所有电脑系统都支持基本拉丁字母,并各自支持不同的其他编码方式。Unicode为了和它们相互兼容,其首256字符保留给ISO 8859-1所定义的字符,使既有的西欧语系文字的转换不需特别考量;并且把大量相同的字符重复编到不同的字符码中去,使得旧有纷杂的编码方式得以和Unicode编码间互相直接转换,而不会丢失任何信息。举例来说,全角格式区段包含了主要的拉丁字母的全角格式,在中文、日文、以及韩文字形当中,这些字符以全角的方式来呈现,而不以常见的半角形式显示,这对竖排文字和等宽排列文字有重要作用。
      在表示一个Unicode的字符时,通常会用“U+”然后紧接着一组十六进制的数字来表示这一个字符。在基本多文种平面(英文为 Basic Multilingual Plane,简写 BMP。它又简称为“零号平面”, plane 0)里的所有字符,要用四位十六进制数(例如U+4AE0,共支持六万多个字符);在零号平面以外的字符则需要使用五位或六位十六进制数了。旧版的Unicode标准使用相近的标记方法,但却有些微的差异:在Unicode 3.0里使用“U-”然后紧接着八位数,而“U+”则必须随后紧接着四位数。[1]
   

   总结也就一句话,Unicode可以实现与各种编码之间相互转化。他就像一个父类,有了多个儿子,儿子各不相同,但都流传着父亲的基因。

  知道了这一点接下来我们就可以开始干了,捋一捋思路,我们首先将utf-8环境下的“动漫卡通”转化为Unicode编码下A,然后再讲A转换为GBK编码下的B(得到纯正的GBK编码),然后在将B转换为Unicode编码下的C;

接下来我们试一试是不是这样尼,我们打印出一条日志:

03-12 17:12:55.869 23869-23869/com.itwangxia.hackhome I/----GAME->>>>: encodeUTF: 动漫卡通   utf2gbk = \U52A8\U6F2B\U5361\UFFFF901A     utf2unicode = \U52A8\U6F2B\U5361\UFFFF901A

可以发现,我们在将UTF编码转为Unicode编码下的B的时候已经得到了需要的编码(排除\U以及FFFF的干扰)

至于为什么是这样,我将在下一篇博客中介绍编码的问题。


实现了诸如%25u52A8%25u6F2B%25u5361%25u901A此类的编码。

接下来粘贴代码,主要是其他编码转换为Unicode编码,至于编码之间互相转换还是借助Unicode编码来实现的。

 
/**
*将GBK编码转换为UTF-8编码
*
*/
public String gbk2utf8(String gbk) {
            String l_temp = GBK2Unicode(gbk);
            l_temp = unicodeToUtf8(l_temp);

            return l_temp;
 
       }
/**
*将UTF-8编码转换为GBK编码
*
*/
public static String utf82gbk(String utf) {
            String l_temp = utf8ToUnicode(utf);
            l_temp = Unicode2GBK(l_temp);

            return l_temp;
        }

 
/**
*将gbk编码转换为unicode编码
*主要编码方法
*/
public static String GBK2Unicode(String str) {            StringBuffer result = new StringBuffer();            for (int i = 0; i < str.length(); i++) {                char chr1 = (char) str.charAt(i);                if (!isNeedConvert(chr1)) {                    result.append(chr1);                    continue;                }                result.append("\\u" + Integer.toHexString((int) chr1));            }            return result.toString();        }       
/**
*将Unicode编码转换为GBK编码
*主要解码方法
*/
public static String Unicode2GBK(String dataStr) {
            int index = 0;
            StringBuffer buffer = new StringBuffer();

            int li_len = dataStr.length();
            while (index < li_len) {
                if (index >= li_len - 1
                        || !"\\u".equals(dataStr.substring(index, index + 2))) {
                    buffer.append(dataStr.charAt(index));

                    index++;
                    continue;
                }

                String charStr = "";
                charStr = dataStr.substring(index + 2, index + 6);

                char letter = (char) Integer.parseInt(charStr, 16);

                buffer.append(letter);
                index += 6;
            }

            return buffer.toString();
        }

        public static boolean isNeedConvert(char para) {
            return ((para & (0x00FF)) != para);
        }

 
/**
*将UTF-8编码转换为Unicode编码
*主要编码方法
*/      
public static String utf8ToUnicode(String inStr) {
            char[] myBuffer = inStr.toCharArray();

            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < inStr.length(); i++) {
//                char ch=myBuffer[i];
//                if((int)ch < 10){
//                    sb.append("\\u000"+(int)ch);
//                    continue;
//                }
                UnicodeBlock ub = UnicodeBlock.of(myBuffer[i]);
                if (ub == UnicodeBlock.BASIC_LATIN) {
                    sb.append(myBuffer[i]);
                } else if (ub == UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
                    int j = (int) myBuffer[i] - 65248;
                    sb.append((char) j);
                } else {
                    short s = (short) myBuffer[i];
                    String hexS = Integer.toHexString(s);
                    String unicode = "\\u" + hexS;
                    sb.append(unicode.toUpperCase());
                }
            }
            return sb.toString();
        }


/**
*将UTF-8编码转换为GBK编码
*主要解码方法
*/      
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();
        }

接下来介绍一些其他方法以帮助浏览此博文的朋友

  

try {
    String s = new String("卡通动漫".getBytes(), "GBK");
} catch (UnsupportedEncodingException e) {
    e.printStackTrace();
}

该方法是不可取的,得到的是乱码,不建议使用

而如果像是这种乱码&#36827;&#20837;&#28216;&#25103;&#8594;&#28857;&#24038;&#19978;&#35282;&#22836;&#20687;&#8594;&#20817;&#25442;&#30721;

使用

Html.fromHtml(String.format(formate,gDesc))

就足以搞定了,主要是后台防止文字乱码问题。

javaScript中的常用escape()编码 和unescape()解码

     escape编码例如中文:网侠小鲜肉  escape编码为:%u7f51%u4fa0%u5c0f%u9c9c%u8089

  1.  public static String escape(String src) {  
  2.         int i;  
  3.         char j;  
  4.         StringBuffer tmp = new StringBuffer();  
  5.         tmp.ensureCapacity(src.length() * 6);  
  6.         for (i = 0; i < src.length(); i++) {  
  7.             j = src.charAt(i);  
  8.             if (Character.isDigit(j) || Character.isLowerCase(j)  
  9.                     || Character.isUpperCase(j))  
  10.                 tmp.append(j);  
  11.             else if (j < 256) {  
  12.                 tmp.append("%");  
  13.                 if (j < 16)  
  14.                     tmp.append("0");  
  15.                 tmp.append(Integer.toString(j, 16));  
  16.             } else {  
  17.                 tmp.append("%u");  
  18.                 tmp.append(Integer.toString(j, 16));  
  19.             }  
  20.         }  
  21.         return tmp.toString();  
  22.     } 
  

   unescape解码

  1.  public static String unescape(String src) {  
  2.         StringBuffer tmp = new StringBuffer();  
  3.         tmp.ensureCapacity(src.length());  
  4.         int lastPos = 0, pos = 0;  
  5.         char ch;  
  6.         while (lastPos < src.length()) {  
  7.             pos = src.indexOf("%", lastPos);  
  8.             if (pos == lastPos) {  
  9.                 if (src.charAt(pos + 1) == 'u') {  
  10.                     ch = (char) Integer.parseInt(src  
  11.                             .substring(pos + 2, pos + 6), 16);  
  12.                     tmp.append(ch);  
  13.                     lastPos = pos + 6;  
  14.                 } else {  
  15.                     ch = (char) Integer.parseInt(src  
  16.                             .substring(pos + 1, pos + 3), 16);  
  17.                     tmp.append(ch);  
  18.                     lastPos = pos + 3;  
  19.                 }  
  20.             } else {  
  21.                 if (pos == -1) {  
  22.                     tmp.append(src.substring(lastPos));  
  23.                     lastPos = src.length();  
  24.                 } else {  
  25.                     tmp.append(src.substring(lastPos, pos));  
  26.                     lastPos = pos;  
  27.                 }  
  28.             }  
  29.         }  
  30.         return tmp.toString();  
  31.     }
  32. 但是切记在安卓开发过程中,我们需要注意使用的网络请求框架的编码方式,如果不注意很有可能报错如下:

              这时我们只需要在在escape编码里面将“%u”换成“%25u”即可

(以上是我个人开发中面对的一些问题及困惑,若有误导,望君海涵,也望君扶正,谢谢)

  

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值