使用Java将中文字符转换成Unicode编码

简介:
 

这两天操作XML使用到了Jdom,在创建XML文件并输出到硬盘的时候遇到一个中文编码的问题:Jdom默认输出的XML编码是UTF-8,但是文档中如果出现中文字符那么该中文字符就会变成乱码,造成XML文件无法被正确解析。

UTF-8应该是可以用来表示中文的吧?我不知道这是不是Jdom的一个BUG(Jdom 1.0,beta了10次的产物哦!)。我google了一下,大家解决这个问题的办法无非是把Jdom的输出字符集改为GBK或者GB2312,但是这样就会有一些副作用,如果在没有特定字符集(GBK或者GB2312)的操作系统上不是依然不能正确解析吗?一个比较好的解决办法是先把中文转换成Unicode编码在直接输出,程序解析XML后的时候再把Unicode编码转回中文就没有问题了。

于是我查看了JDK的文档,截至Java 5好像都没有做类似转换的类可以直接使用,但是我发现一个类 java.util.Properties,它的源代码里有两个私有(private)方法 loadConvert (char[] in, int off, int len, char[] convtBuf) 和 saveConvert(String theString, boolean escapeSpace) 其实就是做特殊字符和Unicode编码字符间转换的,我把它们提取出来,单独包装到一个类里就可以使用了。

下面是我包装的类 CharacterSetToolkit

/*
* CharacterSetToolkit.java
*
* Created on 2006年10月27日, 下午2:06
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/

package mobi.chenwei.lang;

/**
* 进行字符操作的工具类
* @author Chen Wei
* @email
chenwei.mobi@gmail.com
*/
public class CharacterSetToolkit {
    
     /** Creates a new instance of CharacterSetToolkit */
     public CharacterSetToolkit() {
     }
    
     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 码转换成编码前的特殊字符串。
      * @param in Unicode编码的字符数组。
      * @param off 转换的起始偏移量。
      * @param len 转换的字符长度。
      * @param convtBuf 转换的缓存字符数组。
      * @return 完成转换,返回编码前的特殊字符串。
      */
     public String fromUnicode(char[] in, int off, int len, char[] convtBuf) {
         if (convtBuf.length < len) {
             int newLen = len * 2;
             if (newLen < 0) {
                 newLen = Integer.MAX_VALUE;
             }
             convtBuf = new char[newLen];
         }
         char aChar;
         char[] out = convtBuf;
         int outLen = 0;
         int end = off + len;

         while (off < end) {
             aChar = in[off++];
             if (aChar == '\\') {
                 aChar = in[off++];
                 if (aChar == 'u') {
                     // Read the xxxx
                     int value = 0;
                     for (int i = 0; i < 4; i++) {
                         aChar = in[off++];
                         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.");
                         }
                     }
                     out[outLen++] = (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';
                     }
                     out[outLen++] = aChar;
                 }
             } else {
                 out[outLen++] = (char) aChar;
             }
         }
         return new String(out, 0, outLen);
     }
}

相关文章
|
2月前
|
安全 Java API
告别繁琐编码,拥抱Java 8新特性:Stream API与Optional类助你高效编程,成就卓越开发者!
【8月更文挑战第29天】Java 8为开发者引入了多项新特性,其中Stream API和Optional类尤其值得关注。Stream API对集合操作进行了高级抽象,支持声明式的数据处理,避免了显式循环代码的编写;而Optional类则作为非空值的容器,有效减少了空指针异常的风险。通过几个实战示例,我们展示了如何利用Stream API进行过滤与转换操作,以及如何借助Optional类安全地处理可能为null的数据,从而使代码更加简洁和健壮。
80 0
|
18天前
|
存储 移动开发 Java
java核心之字符串与编码
java核心之字符串与编码
14 2
|
2月前
|
Java
Java系列之:字符串UTF-8 编码格式转换位 UTF-32 【生僻字截取问题】
这篇文章讨论了在Java中处理包含生僻字的字符串时可能遇到的问题,并提供了一种解决方法:将字符串的编码格式从UTF-8转换为UTF-32,以确保每个字符都占用固定的字节数,从而避免在截取操作中破坏字符,示例代码展示了如何进行编码转换和字符串截取。
|
2月前
|
存储 安全 Java
"Java编码魔法:揭秘图片与文件的Base64神秘转换术,让数据在指尖跳跃!"
【8月更文挑战第16天】Base64编码在Java开发中常用于将二进制数据如图片转换为ASCII字符串以便传输。编码使用64个字符及等号填充,每3字节数据编码为4个字符。Java利用`java.util.Base64`类实现此功能:读取图片或文件为字节数组后进行编码。解码时将Base64字符串还原为字节数组并写入文件。需注意编码效率降低、不提供安全性及特殊字符兼容性等问题。掌握这些技巧有助于解决Web开发中的数据传输需求。
73 4
|
2月前
|
Java PHP 开发者
PHP中的异常处理:Java常见的编码方式
在PHP开发中,掌握异常处理至关重要,它有助于预见并管理运行时错误,避免用户体验受损或数据丢失。本文介绍PHP异常处理的基本概念与实践,包括try-catch语句的使用,以及如何通过抛出和捕获异常来增强代码的健壮性和可靠性。通过示例展示如何避免常见错误,如除数为零的情况,并探讨多catch块和finally语句的高级用法,帮助开发者提升程序稳定性与可维护性。[总字符数:238]
26 0
|
Java
教妹学Java(十):Unicode字符集简介
教妹学Java(十):Unicode字符集简介
198 0
|
15天前
|
安全 Java 调度
Java编程时多线程操作单核服务器可以不加锁吗?
Java编程时多线程操作单核服务器可以不加锁吗?
37 2
|
4天前
|
Java 关系型数据库 MySQL
如何用java的虚拟线程连接数据库
本文介绍了如何使用Java虚拟线程连接数据库,包括设置JDK版本、创建虚拟线程的方法和使用虚拟线程连接MySQL数据库的示例代码。
17 6
如何用java的虚拟线程连接数据库
|
8天前
|
Java 数据库 UED
Java的多线程有什么用
Java的多线程技术广泛应用于提升程序性能和用户体验,具体包括:提高性能,通过并行执行充分利用多核CPU;保持响应性,使用户界面在执行耗时操作时仍流畅交互;资源共享,多个线程共享同一内存空间以协同工作;并发处理,高效管理多个客户端请求;定时任务,利用`ScheduledExecutorService`实现周期性操作;任务分解,将大任务拆分以加速计算。多线程尤其适用于高并发和并行处理场景。
|
4天前
|
Java 调度
Java一个线程的生命周期详解
Java中,一个线程的生命周期分为五个阶段:NEW(新建),RUNNABLE(可运行),BLOCKED(阻塞),WAITING(等待),TERMINATED(终止)。线程创建后处于新建状态,调用start方法进入可运行状态,执行中可能因等待资源进入阻塞或等待状态,正常完成或异常终止后进入终止状态。各状态间可相互转换,构成线程的生命周期。

热门文章

最新文章