/**
* 获取字符串的unicode编码
* 汉字“木”的Unicode 码点为Ox6728
*
* @param s 木
* @return \ufeff\u6728 \ufeff控制字符 用来表示「字节次序标记(Byte Order Mark)」不占用宽度
*/
public static String stringToUnicode(String s) {
try {
StringBuffer out = new StringBuffer("");
//直接获取字符串的unicode二进制
byte[] bytes = s.getBytes("unicode");
//然后将其byte转换成对应的16进制表示即可
for (int i = 0; i < bytes.length - 1; i += 2) {
out.append("\\u");
String str = Integer.toHexString(bytes[i + 1] & 0xff);
for (int j = str.length(); j < 2; j++) {
out.append("0");
}
String str1 = Integer.toHexString(bytes[i] & 0xff);
out.append(str1);
out.append(str);
}
return out.toString();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
测试
@Test
public void testGetUnicode() throws Exception {
String str = "木";
String s = EncodeUtil.stringToUnicode(str);
System.out.println(s); //Ox6728
}
/**
* Unicode转 汉字字符串
*
* @param str \u6728
* @return '木' 26408
*/
public static String unicodeToString(String str) {
Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))");
Matcher matcher = pattern.matcher(str);
char ch;
while (matcher.find()) {
//group 6728
String group = matcher.group(2);
//ch:'木' 26408
ch = (char) Integer.parseInt(group, 16);
//group1 \u6728
String group1 = matcher.group(1);
str = str.replace(group1, ch + "");
}
return str;
}
测试
@Test
public void testUnicodeToString() throws Exception {
String str = "\\u6728";
String s = EncodeUtil.unicodeToString(str);
System.out.println(s); //木
}
/**
* 汉字 转换为对应的 UTF-8编码
* @param s 木
* @return E69CA8
*/
public static String convertStringToUTF8(String s) {
if (s == null || s.equals("")) {
return null;
}
StringBuffer sb = new StringBuffer();
try {
char c;
for (int i = 0; i < s.length(); i++) {
c = s.charAt(i);
if (c >= 0 && c <= 255) {
sb.append(c);
} else {
byte[] b;
b = Character.toString(c).getBytes("utf-8");
for (int j = 0; j < b.length; j++) {
int k = b[j];
//转换为unsigned integer 无符号integer
/*if (k < 0)
k += 256;*/
k = k < 0? k+256:k;
//返回整数参数的字符串表示形式 作为十六进制(base16)中的无符号整数
//该值以十六进制(base16)转换为ASCII数字的字符串
sb.append(Integer.toHexString(k).toUpperCase());
// url转置形式
// sb.append("%" +Integer.toHexString(k).toUpperCase());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return sb.toString();
}
测试
@Test
public void testConvertStringToUTF8() {
String str = "木";
String s = EncodeUtil.convertStringToUTF8(str);
System.out.println(s); //E69CA8
}
/**
* UTF-8编码 转换为对应的 汉字
*
* @param s E69CA8
* @return 木
*/
public static String convertUTF8ToString(String s) {
if (s == null || s.equals("")) {
return null;
}
try {
s = s.toUpperCase();
int total = s.length() / 2;
//标识字节长度
int pos = 0;
byte[] buffer = new byte[total];
for (int i = 0; i < total; i++) {
int start = i * 2;
//将字符串参数解析为第二个参数指定的基数中的有符号整数。
buffer[i] = (byte) Integer.parseInt(s.substring(start, start + 2), 16);
pos++;
}
//通过使用指定的字符集解码指定的字节子阵列来构造一个新的字符串。
//新字符串的长度是字符集的函数,因此可能不等于子数组的长度。
return new String(buffer, 0, pos, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return s;
}
测试
@Test
public void testConvertUTF8ToString() {
String str = "E69CA8";
String s = EncodeUtil.convertUTF8ToString(str);
System.out.print(s); //木
}
//将unicode转换为utf-8
@Test
public void testUnicodeToUtf8() {
String str = "\\u6728";
//unicode转换为String String再转换为utf-8
String s = EncodeUtil.convertStringToUTF8(EncodeUtil.unicodeToString(str));
System.out.println(s);
}
//将utf-8转换为unicode
@Test
public void testUTF8ToUnicode() {
String str = "E69CA8";
//utf-8先转String String再转unicode
String s = EncodeUtil.stringToUnicode(EncodeUtil.convertUTF8ToString(str));
System.out.println(s);
}
总结来说:
1. java中的一个char是两个字节,采用unicode字符集,使用指定的编码方式存储在内存中。
2. 一个典型的错误是
String s = new String(”木”.getBytes(“utf-8”),”gbk”);
为什么会报错呢?原因是 utf-8编码的字节数组怎能使用gbk来解析呢?一个汉字在utf-8下占用3个字节,而在gbk下占用2个字节,是无法解析的。
3. java中提供了将汉字编码为utf8的方法 UrlEncoder.encode()以及解码的方法UrlDecoder.decode()
工具类源码:https://gitee.com/constfafa/data_structure_and_algorithm/blob/master/util/main/java/EncodeUtil.java
测试类源码:https://gitee.com/constfafa/data_structure_and_algorithm/blob/master/util/test/java/EncodingUtilTest.java
参考:
Java unicode中文编码转换和反转
java 汉字与UTF-8十六进制编码 间相互转换方法
java中char与汉字占用字节个数问题