`
angie_hawk7
  • 浏览: 48624 次
  • 性别: Icon_minigender_1
  • 来自: 乌托邦
社区版块
存档分类
最新评论

GBK与UTF-8之间的转换

阅读更多

引用
该篇文章引用自:http://www.blogjava.net/pengpenglin/archive/2010/02/22/313669.html

【GBK转UTF-8】


--------------------------------------------------------------------------------
在很多论坛、网上经常有网友问“ 为什么我使用 new String(tmp.getBytes("ISO-8859-1"), "UTF-8") 或者 new String(tmp.getBytes("ISO-8859-1"), "GBK")可以得到正确的中文,但是使用 new String(tmp.getBytes("GBK"), "UTF-8") 却不能将GBK转换成UTF-8呢?”

参考前面的【Java基础专题】编码与乱码(03)----String的toCharArray()方法测试 一文,我们就知道原因了。因为如果客户端使用GBK、UTF-8编码,编码后的字节经过ISO-8859-1传输,再用原来相同的编码方式进行解码,这个过程是“无损的转换”---- 因为原始和最终的编码方式相同。

但是如果客户端使用GBK编码,到了服务器端要转换成UTF-8,或者相反的过程。想一想,字节还是那些字节,但是编码的规则变了。原来GBK编码后的4个字节要用UTF-8的每个字符3个字节的规则编码,怎么能不乱码呢?

所以从现在开始,不要再犯这种错误了。new String(tmp.getBytes("GBK"), "UTF-8") 这个过程,JVM内部是不会帮你自动对字节进行扩展以适应UTF-8的编码的。正确的方法应该是根据UTF-8的编码规则进行字节的扩充,即手动从2个字节变成3个字节,然后再转换成十六进制的UTF-8编码。

在这个专题的第一篇文章【Java基础专题】编码与乱码(01)---编码基础 开头,我们就已经介绍了这个规则:
①得到每个字符的2进制GBK编码
②将该16进制的GBK编码转换成2进制的字符串(2个字节)
③分别在字符串的首位插入110,在第9位插入10,在第17位插入10三个字符串,得到3个字节
④将这3个字节分别转换成16进制编码,得到最终的UTF-8编码。




下面给出一个从网络上得到的Java转码方法,原文链接见:http://jspengxue.iteye.com/blog/40781。下面的代码做了小小的修改
package example.encoding;

/** *//**
 * The Class CharacterEncodeConverter.
 */
public class CharacterEncodeConverter {

    /** *//**
     * The main method.
     * 
     * @param args the arguments
     */
    public static void main(String[] args) {

        try {
            CharacterEncodeConverter convert = new CharacterEncodeConverter();
            byte[] fullByte = convert.gbk2utf8("中文");
            String fullStr = new String(fullByte, "UTF-8");
            System.out.println("string from GBK to UTF-8 byte:  " + fullStr);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /** *//**
     * Gbk2utf8.
     * 
     * @param chenese the chenese
     * 
     * @return the byte[]
     */
    public byte[] gbk2utf8(String chenese) {
        
        // Step 1: 得到GBK编码下的字符数组,一个中文字符对应这里的一个c[i]
        char c[] = chenese.toCharArray();
        
        // Step 2: UTF-8使用3个字节存放一个中文字符,所以长度必须为字符的3倍
        byte[] fullByte = new byte[3 * c.length];
        
        // Step 3: 循环将字符的GBK编码转换成UTF-8编码
        for (int i = 0; i < c.length; i++) {
            
            // Step 3-1:将字符的ASCII编码转换成2进制值
            int m = (int) c[i];
            String word = Integer.toBinaryString(m);
            System.out.println(word);

            // Step 3-2:将2进制值补足16位(2个字节的长度) 
            StringBuffer sb = new StringBuffer();
            int len = 16 - word.length();
            for (int j = 0; j < len; j++) {
                sb.append("0");
            }
            // Step 3-3:得到该字符最终的2进制GBK编码
            // 形似:1000 0010 0111 1010
            sb.append(word);
            
            // Step 3-4:最关键的步骤,根据UTF-8的汉字编码规则,首字节
            // 以1110开头,次字节以10开头,第3字节以10开头。在原始的2进制
            // 字符串中插入标志位。最终的长度从16--->16+3+2+2=24。
            sb.insert(0, "1110");
            sb.insert(8, "10");
            sb.insert(16, "10");
            System.out.println(sb.toString());

            // Step 3-5:将新的字符串进行分段截取,截为3个字节
            String s1 = sb.substring(0, 8);
            String s2 = sb.substring(8, 16);
            String s3 = sb.substring(16);

            // Step 3-6:最后的步骤,把代表3个字节的字符串按2进制的方式
            // 进行转换,变成2进制的整数,再转换成16进制值
            byte b0 = Integer.valueOf(s1, 2).byteValue();
            byte b1 = Integer.valueOf(s2, 2).byteValue();
            byte b2 = Integer.valueOf(s3, 2).byteValue();
            
            // Step 3-7:把转换后的3个字节按顺序存放到字节数组的对应位置
            byte[] bf = new byte[3];
            bf[0] = b0;
            bf[1] = b1;
            bf[2] = b2;
            
            fullByte[i * 3] = bf[0];            
            fullByte[i * 3 + 1] = bf[1];            
            fullByte[i * 3 + 2] = bf[2];
            
            // Step 3-8:返回继续解析下一个中文字符
        }
        return fullByte;
    }
}

最终的测试结果是正确的:string from GBK to UTF-8 byte:  中文。

但是这个方法并不是完美的!要知道这个规则只对中文起作用,如果传入的字符串中包含有单字节字符,如a+3中文,那么解析的结果就变成:string from GBK to UTF-8 byte:  ?????????中文了。为什么呢?道理很简单,这个方法对原本在UTF-8中应该用单字节表示的数字、英文字符、符号都变成3个字节了,所以这里有9个?,代表被转换后的a、+、3字符。

所以要让这个方法更加完美,最好的方法就是加入对字符Unicode区间的判断

UCS-2编码(16进制) UTF-8 字节流(二进制)
0000 - 007F 0xxxxxxx
0080 - 07FF 110xxxxx 10xxxxxx
0800 - FFFF 1110xxxx 10xxxxxx 10xxxxxx







汉字的Unicode编码范围为\u4E00-\u9FA5 \uF900-\uFA2D,如果不在这个范围内就不是汉字了。

【UTF-8转GBK】

道理和上面的相同,只是一个逆转的过程,不多说了

但是最终的建议还是:能够统一编码就统一编码吧!要知道编码的转换是相当的耗时的工作



  • 大小: 39.4 KB
分享到:
评论

相关推荐

    GBK、UTF-8编码转换工具

    GBK、UTF-8批量文件3秒快速转码工具(支持GBK,UTF-8免费转换),UTF-8/GBK编码在线转换工具,压缩包可以有多目录与文件,如目录中有图片不会转码,但是会随转码好的文件一起打包下载。 使用帮助 . 上传压缩包(仅支持zip...

    c gbk和 utf-8 转换

    在C语言中,由于没有内置的GBK或UTF-8转换函数,我们需要自定义算法来实现编码转换。主要的过程可以分为两个步骤:首先从GBK转换到Unicode,然后从Unicode转换到UTF-8。 1. GBK转Unicode: - GBK编码中,每个字符...

    GBK与UTF-8转码(C++)

    本文将详细介绍如何在Microsoft Foundation Classes (MFC)环境下实现GBK与UTF-8之间的编码转换。该技术适用于那些需要处理不同字符集数据的应用程序开发场景,特别是在早期Windows系统中广泛使用的MFC框架下进行编码...

    C#写的 GBK GB2312 UTF-8转换

    在这个例子中,`Encoding.GetEncoding("GBK")`获取了GBK编码器,`GetBytes()`方法将GBK编码的字符串转换为字节数组,然后`Encoding.UTF8.GetString()`将这个字节数组还原为UTF-8编码的字符串。 对于文件的编码转换...

    UTF-8toGBK_labview编码gbk_LabVIEWUTF-8_utf-8toGbk_

    本篇文章将详细探讨UTF-8与GBK编码,以及如何在LabVIEW环境下进行这两种编码之间的转换。 首先,UTF-8(Unicode Transformation Format - 8 bit)是一种变长的Unicode编码,它使用1到4个字节来表示一个字符。UTF-8...

    GBK 与 UTF-8 间编码转换

    在实际应用中,GBK和UTF-8之间的转换问题常常出现,尤其是在处理不同来源的数据时。例如,GBK编码的文件可能无法在支持UTF-8的系统中正确显示,反之亦然。描述中提到的“用vs2017写的”小程序就是为了解决这个问题,...

    GBK<-->UTF-8格式转换

    # 从UTF-8转换为GBK with codecs.open('UTF8_file.txt', 'r', 'utf-8') as utf8_file: content = utf8_file.read() with codecs.open('GBK_file.txt', 'w', 'gbk') as gbk_file: gbk_file.write(content) ``` 在...

    C语言字符编码转换UNICODE、GBK、UTF-8互相转换

    在这个主题中,我们将深入探讨如何在C语言中进行UNICODE、GBK和UTF-8之间的转换。 UNICODE,也称为Unicode Transformation Format(UTF),是一种标准的字符编码,旨在表示世界上所有语言的每一个字符。它使用数字...

    eclipse中class乱码GBK-UTF-8转换工具

    这篇博客文章“eclipse中class乱码GBK-UTF-8转换工具”正是为了解决这个问题。 GBK是GB2312的扩展,包含了更多的汉字和其他字符,主要在中国大陆使用。UTF-8则是一种广泛使用的Unicode编码,支持世界上几乎所有的...

    c语言gbk、utf8转换编码表及函数

    - 在C语言中,我们可以编写函数来实现GBK和UTF-8之间的转换。文件`utf8gbk.h`和`utf8gbk.c`可能包含了这样的转换函数。 - 通常,从GBK转UTF-8需要将每个GBK编码的双字节序列转换为对应的Unicode码点,然后根据UTF-...

    gbk转换utf-8工具!绝对给力!

    这些标签强调了工具的核心功能,即在GBK与UTF-8编码之间进行转换,这对于处理中文字符在不同系统或平台间兼容性问题非常重要。 在压缩包中的“GBK-UTF8.exe”文件名表明这可能是一个可执行文件,用户在Windows环境...

    gbk和 utf-8 转换

    在C语言中,没有内置的GBK或UTF-8转换函数,因此需要手动编写转换算法。通常,这种转换涉及查找和使用字符映射表。GBK编码的每个字符都有一个对应的Unicode码点,而Unicode码点又可以转换为UTF-8编码。转换过程大致...

    文件编码转换,GBK和UTF-8双向互换,批处理文化方法

    文件包含:gbk2utf-8.bat、utf-82gbk.bat、iconv.exe及使用说明.txt四个文件 使用说明:1把要转换的所有.h和.c文件拷入该目录下,双击相应的bat文件即可。 2转换结果会保存在utf-8Res或gbkRes目录下。 3如果转换除...

    批量将Java源代码文件的编码从GBK转为UTF-8

    老项目采用GBK编码格式,而新项目采用的UTF-8编码格式,如果直接把Java源代码复制到Eclipse中所有的中文信息会出现乱码。所以写了个小的方法类,将java文件的编码格式从GBK转UTF-8

    Eclipse项目的GBK编码转为UTF-8插件

    总的来说,"Eclipse项目的GBK编码转为UTF-8插件"是解决GBK到UTF-8编码转换问题的有效工具,它简化了开发者的工作流程,提高了代码管理的效率。对于那些经常需要处理不同编码格式项目的人来说,这样的工具无疑是非常...

    gbk转utf-8批量转换

    标题中的“GBK转UTF-8批量转换”是指在计算机编程和文本处理领域中常见的字符编码转换过程。GBK和UTF-8是两种不同的字符编码标准,它们用于表示不同语言的字符集,尤其是中文字符。 GBK(Great Chinese Encoding)...

    JAVA字符编码:Unicode,ISO-8859-1,GBK,UTF-8编码及相互转换

    本文将详细介绍Unicode、ISO-8859-1、GBK和UTF-8这四种常见的字符编码,并探讨它们之间的转换方法。 #### 二、基础知识 ##### 1. Unicode Unicode是一种国际字符编码标准,旨在支持世界上几乎所有语言的文字。它为...

    GBK编码转换和UTF-8编码转换模块源码

    GBK编码和UTF-8编码是两种广泛使用的字符编码标准,它们各有特点,但不兼容,因此在不同环境下进行数据交换时,需要进行相应的转换。 GBK编码是中国大陆广泛采用的一种汉字编码标准,它是GB2312的扩展,包含了更多...

Global site tag (gtag.js) - Google Analytics