首页 > 编程语言 >Java 中文字符串编码之GBK转UTF-8

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

时间:2023-01-04 15:45:41浏览次数:48  
标签:编码 UTF 字节 16 GBK gbk utfBytes Java byte

写过两篇关于编码的文章了,以为自己比较了解编码了呢?!

结果今天又结结实实的上了一课。

以前转来转去解决的问题终归还是简单的情形。即iso-8859-1转utf-8,或者iso-8859-1转gbk,gb2312之类。这种无损转换,一行代码就搞定。

今天遇到了gbk转utf-8。无论怎么转,都是乱码。

一、乱码的原因

gbk的中文编码是一个汉字用【2】个字节表示,例如汉字“内部”的gbk编码16进制的显示为c4 da b2 bf

utf-8的中文编码是一个汉字用【3】个字节表示,例如汉字“内部”的utf-8编码16进制的显示为e5 86 85 e9 83 a8

很显然,gbk是无法直接转换成utf-8,少字节变为多字节,谁知道缺少的字节是什么啊?!

二、转换的办法

有办法实现“有损”转换吗?答案是肯定的。

1.首先将gbk字符串getBytes()得到两个原始字节,转换成二进制字符流,共16位。

2.根据UTF-8的汉字编码规则,首字节以1110开头,次字节以10开头,第3字节以10开头。在原始的2进制字符串中插入标志位。最终的长度从16--->16+4+2+2=24。

3.转换完成,实际情况需要考虑更多因素,例如字符串是汉字和数字的混合体,需要识别处理数字。

三、不要重复发明轮子

这段代码测试可用还很好用,需要的可以参考。

复制代码
 1 public static String getUTF8StringFromGBKString(String gbkStr) {  
 2         try {  
 3             return new String(getUTF8BytesFromGBKString(gbkStr), "UTF-8");  
 4         } catch (UnsupportedEncodingException e) {  
 5             throw new InternalError();  
 6         }  
 7     }  
 8       
 9     public static byte[] getUTF8BytesFromGBKString(String gbkStr) {  
10         int n = gbkStr.length();  
11         byte[] utfBytes = new byte[3 * n];  
12         int k = 0;  
13         for (int i = 0; i < n; i++) {  
14             int m = gbkStr.charAt(i);  
15             if (m < 128 && m >= 0) {  
16                 utfBytes[k++] = (byte) m;  
17                 continue;  
18             }  
19             utfBytes[k++] = (byte) (0xe0 | (m >> 12));  
20             utfBytes[k++] = (byte) (0x80 | ((m >> 6) & 0x3f));  
21             utfBytes[k++] = (byte) (0x80 | (m & 0x3f));  
22         }  
23         if (k < utfBytes.length) {  
24             byte[] tmp = new byte[k];  
25             System.arraycopy(utfBytes, 0, tmp, 0, k);  
26             return tmp;  
27         }  
28         return utfBytes;  
29     }  
复制代码

PS:有点儿对不住原作者,找了很多代码,一一测试,结果网页都关闭了,如果有大神认领,我一定补充链接,而且深表感谢。

标签:编码,UTF,字节,16,GBK,gbk,utfBytes,Java,byte
From: https://www.cnblogs.com/kn-zheng/p/17025035.html

相关文章

  • Linux删除多个java进程的其中一个
    一、背景:Linux后台运行了多个Java程序,进程名都是java。执行pkilljava会一次性杀掉所有的java进程。二、解决思路:1先通过一定的检索条件,定位出指定的java进程23......
  • java LinkedHashMap学习
    一、LinkedHashMap概述LinkedHashMap是HashMap的一个子类,它保留插入的顺序,如果需要输出的顺序和输入时的相同,那么就选用LinkedHashMap。LinkedHashMap是Map接口的哈希表......
  • freeswitch编译java esl
    一、背景假设源代码路径为/home/freeswitch二、编译安装libesl.a1.cd/home/freeswitch(源代码的根目录)执行./configure,以便生成必要的Makefile文件。2.cd/home/fre......
  • Java程序(非web)slf4j整合Log4j2
    一、依赖包准备//slf4j项目提供compilegroup:'org.slf4j',name:'slf4j-api',version:'1.7.25'//log4j2项目提供compilegroup:'org.apache.logging.log4j',na......
  • JAVA命令行编译及运行
    第一部分:单文件一、背景目标文件HelloWorld.javapackageccdate;publicclassHelloWorld{publicstaticvoidmain(String[]args){......
  • sun.security.validator.ValidatorException: PKIXpath building failed: sun.securit
    报错信息:javax.net.ssT.SSLHandshakeExceptions.certpath.SunCertPathBuilderException:unabletofindvalidcertificationpathtoreguestedtarget问题描述:在ja......
  • Java调用Linux命令(cd的处理)
    一、Java调用Linux系统的命令非常简单这是一个非常常用的调用方法示例:1publicStringexecuteLinuxCmd(Stringcmd){2System.out.println("gotcmd......
  • [java] a simple Applet program
    //javacodefileimportjavax.swing.*;importjava.awt.*;importjava.awt.event.*;importjava.net.*;publicclassWelcomeAppletextendsJApplet{publicvoidinit()......
  • [java]Regular Expression Testor
    importjava.awt.Dimension;importjava.awt.GridBagConstraints;importjava.awt.GridBagLayout;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListene......
  • Java线程生命周期
    java.lang.Thread类包含一个静态枚举,它定义了它的潜在状态。在任何给定的时间点内,线程只能处于以下状态之一:NEW–一个新创建的线程,尚未开始执行RUNNABLE–正在运行......