java ucs2转utf8_UCS-2和UTF-8的互相转换
UCS-2是内码,而UTF-8则是它的实现方式。每一个字节都有8个位,而对于UTF-8来说,每一个字节的前两位尤为重要,按照前两位的不同,一共有四种排列组合:00xxxxxx,01xxxxxx,10xxxxxx,11xxxxxx。
按照UTF-8标准,
(1)所有以0开始的字节,都与原来的ASCII码兼容,也就是说,0xxxxxxx不需要额外转换,就是我们平时用的ASCII码。
(2)所有以10开始的字节,都不是每个UNICODE的第一个字节,都是紧跟着前一位。例如:10110101,这个字节不可以单独解析,必须通过前一个字节来解析,如果前一个也是10开头,就继续前嗍。
(3)所有以11开始的字节,都表示是UNICODE的第一个字节,而且后面紧跟着若干个以10开头的字节。如果是110xxxxx(就是最左边的0的左边有2个1),代表后面还有1个10xxxxxx;如果是1110xxxx(就是最左边的0的左边有3个1),代表后面还有2个10xxxxxx;以此类推,一直到1111110x。
具体的表格如下:
1字节 0xxxxxxx
2字节 110xxxxx 10xxxxxx
3字节 1110xxxx 10xxxxxx 10xxxxxx
4字节 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
5字节 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
6字节 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
(很明显,以11开头的,最左边的0左边有多少个1,那这个UCS的UTF-8的表示长度就有多少个字节)
上面是用6个字节,最多可以表示2 ^ 31个的字符,实际上,只有UCS-4才有这么多的字符,对于UCS-2,仅仅有2 ^ 16个字符,只需要三个字节就可以,也就是说,只需要用到下面的格式:
1字节 0xxxxxxx
2字节 110xxxxx 10xxxxxx
3字节 1110xxxx 10xxxxxx 10xxxxxx
大家可以试一下下面的program,来看看UTF-8的每个字节。
Java代码
packagecom.ray.utf8;
importjava.io.UnsupportedEncodingException;
publicclassUTF8Tester {
privatestaticString toBin(intn) {
StringBuilder b =newStringBuilder();
if(n 0) n +=256;
for(inti =7; i >=0; i--) {
if(1== ((n >> i) &1)) {
b.append('1');
}else{
b.append('0');
}
}
returnb.toString();
}
privatestaticString HEX ="0123456789ABCDEF";
privatestaticString toHex(intn) {
StringBuilder b =newStringBuilder();
if(n 0) n +=256;
b.append(HEX.charAt(n >>4));
b.append(HEX.charAt(n &0x0F));
returnb.toString();
}
privatestaticvoidprintUTF8(charch)throwsUnsupportedEncodingException {
String unicode = toHex(ch >>8) + toHex(ch &0xFF);
String unicodeBin = toBin(ch >>8) +' '+ toBin(ch &0xFF);
String s =""+ ch;
byte[] b = s.getBytes("UTF-8");
String hex ="";
for(inti =0; i
hex += toHex((int) b[i]);
hex +=" ";
}
String bin ="";
for(inti =0; i
bin += toBin((int) b[i]);
bin +=" ";
}
String sf = String.format("U+%s %s : %-8s : %s", unicode, unicodeBin, hex.trim(), bin.trim());
System.out.println(sf);
}
publicstaticvoidmain(String[] args)throwsException {
printUTF8('\u002A');
printUTF8('\u012A');
printUTF8('\u012B');
printUTF8('\u052C');
printUTF8('\u013C');
printUTF8('\uAA2A');
printUTF8('\uFDFD');
}
}package com.ray.utf8;
import java.io.UnsupportedEncodingException;
public class UTF8Tester {
private static String toBin(int n) {
StringBuilder b = new StringBuilder();
if (n < 0) n += 256;
for (int i = 7; i >= 0; i--) {
if (1 == ((n >> i) & 1)) {
b.append('1');
} else {
b.append('0');
}
}
return b.toString();
}
private static String HEX = "0123456789ABCDEF";
private static String toHex(int n) {
StringBuilder b = new StringBuilder();
if (n < 0) n += 256;
b.append(HEX.charAt(n >> 4));
b.append(HEX.charAt(n & 0x0F));
return b.toString();
}
private static void printUTF8(char ch) throws UnsupportedEncodingException {
String unicode = toHex(ch >> 8) + toHex(ch & 0xFF);
String unicodeBin = toBin(ch >> 8) + ' ' + toBin(ch & 0xFF);
String s = "" + ch;
byte[] b = s.getBytes("UTF-8");
String hex = "";
for (int i = 0; i < b.length; i++) {
hex += toHex((int) b[i]);
hex += " ";
}
String bin = "";
for (int i = 0; i < b.length; i++) {
bin += toBin((int) b[i]);
bin += " ";
}
String sf = String.format("U+%s %s : %-8s : %s", unicode, unicodeBin, hex.trim(), bin.trim());
System.out.println(sf);
}
public static void main(String[] args) throws Exception {
printUTF8('\u002A');
printUTF8('\u012A');
printUTF8('\u012B');
printUTF8('\u052C');
printUTF8('\u013C');
printUTF8('\uAA2A');
printUTF8('\uFDFD');
}
}
输出:
U+002A 00000000 00101010 : 2A : 00101010
U+012A 00000001 00101010 : C4 AA : 11000100 10101010
U+012B 00000001 00101011 : C4 AB : 11000100 10101011
U+052C 00000101 00101100 : D4 AC : 11010100 10101100
U+013C 00000001 00111100 : C4 BC : 11000100 10111100
U+AA2A 10101010 00101010 : EA A8 AA : 11101010 10101000 10101010
U+FDFD 11111101 11111101 : EF B7 BD : 11101111 10110111 10111101
UCS-2和UTF-8的转换,只涉及到位运算,不需要像GBK般需要查找代码表,所以转换效率很高。
先来说说UTF-8转UCS-2:
(1)对于以0开始的字节,直接在前面部补一个0的字节凑成2个字节(即0xxxxxxx ==> 00000000 0xxxxxxxx);
(2)对于以110开始(110xxxxx)的字节,把后面紧跟着的一个10xxxxxx拿过来,首先在高位字节的左边补5个零,然后把11个“x”放在右边(即110xxxxx 10yyyyyy ==> 00000xxx xxyyyyyy);
(3)对于以1110开始(1110xxxx)的字节,把后面紧跟着的两个10xxxxxx拿过来,数一下,一共有16个“x”,没错,就是把这16个“x”组成两个字节(即1110xxxx 10yyyyyy 10zzzzzz ==> xxxxyyyy yyzzzzzz)。
在来说说UCS-2转UTF-8:
(1)对于不大于0x007F(即00000000 01111111)的,直接把它转成一个字节,变成ASCII;
(2)对于不大于0x07FF(即00000111 11111111)的,转换成两个字节,转换的时候把右边的11位分别放到110xxxxx 10yyyyyy里边,即00000aaa bbbbbbbb ==> 110aaabb 10bbbbbb
(3)剩下的回转换成三个字节,转换的时候也是把16个位分别填写到那三个字节里面,即aaaaaaaa bbbbbbbb ==> 1110aaaa 10aaaabb 10bbcccccc
下面是转换的实现代码:
Java代码
packagecom.ray.utf8;
importjava.io.ByteArrayOutputStream;
importjava.io.UnsupportedEncodingException;
publicclassUtf8Utils {
privatefinalstaticbyteB_10000000 =128-256;
privatefinalstaticbyteB_11000000 =192-256;
privatefinalstaticbyteB_11100000 =224-256;
privatefinalstaticbyteB_11110000 =240-256;
privatefinalstaticbyteB_00011100 =28;
privatefinalstaticbyteB_00000011 =3;
privatefinalstaticbyteB_00111111 =63;
privatefinalstaticbyteB_00001111 =15;
privatefinalstaticbyteB_00111100 =60;
/** Convert from UTF8 bytes to UNICODE character */
publicstaticchar[] toUCS2(byte[] utf8Bytes) {
CharList charList =newCharList();
byteb2 =0, b3 =0;
intub1 =0, ub2 =0;
for(inti =0; i
byteb = utf8Bytes[i];
if(isNotHead(b)) {
// start with 10xxxxxx, skip it.
continue;
}elseif(b >0) {
// 1 byte, ASCII
charList.add((char) b);
}elseif((b & B_11110000) == B_11110000) {
// UCS-4, here we skip it
continue;
}elseif((b & B_11100000) == B_11100000) {
// 3 bytes
b2 = utf8Bytes[i+1];
if(!isNotHead(b2))continue;
i++;
b3 = utf8Bytes[i+1];
if(!isNotHead(b3))continue;
i++;
ub1 = ((b & B_00001111) <4) + ((b2 & B_00111100) >>2);
ub2 = ((b2 & B_00000011) <6) + ((b3 & B_00111111));
charList.add(makeChar(ub1, ub2));
}else{
// 2 bytes
b2 = utf8Bytes[i+1];
if(!isNotHead(b2))continue;
i++;
ub1 = (b & B_00011100) >>2;
ub2 = ((b & B_00000011) <6) + (b2 & B_00111111);
charList.add(makeChar(ub1, ub2));
}
}
returncharList.toArray();
}
privatestaticbooleanisNotHead(byteb) {
return(b & B_11000000) == B_10000000;
}
privatestaticcharmakeChar(intb1,intb2) {
return(char) ((b1 <8) + b2);
}
publicstaticbyte[] fromUCS2(char[] ucs2Array) {
ByteArrayOutputStream baos =newByteArrayOutputStream();
for(inti =0; i
charch = ucs2Array[i];
if(ch <=0x007F) {
baos.write(ch);
}elseif(ch <=0x07FF) {
intub1 = ch >>8;
intub2 = ch &0xFF;
intb1 = B_11000000 + (ub1 <2) + (ub2 >>6);
intb2 = B_10000000 + (ub2 & B_00111111);
baos.write(b1);
baos.write(b2);
}else{
intub1 = ch >>8;
intub2 = ch &0xFF;
intb1 = B_11100000 + (ub1 >>4);
intb2 = B_10000000 + ((ub1 & B_00001111) <2) + (ub2 >>6);
intb3 = B_10000000 + (ub2 & B_00111111);
baos.write(b1);
baos.write(b2);
baos.write(b3);
}
}
returnbaos.toByteArray();
}
privatestaticclassCharList {
privatechar[] data =null;
privateintused =0;
publicvoidadd(charc) {
if(data ==null) {
data =newchar[16];
}elseif(used >= data.length) {
char[] temp =newchar[data.length *2];
System.arraycopy(data,0, temp,0, used);
data = temp;
}
data[used++] = c;
}
publicchar[] toArray() {
char[] chars =newchar[used];
System.arraycopy(data,0, chars,0, used);
returnchars;
}
}
privatestaticvoidassert1(String s)throwsUnsupportedEncodingException {
byte[] b = s.getBytes("utf-8");
char[] c = toUCS2(b);
if(!s.equals(newString(c))) {
thrownewRuntimeException("Can not pass assert1 for: "+ s);
}
}
privatestaticvoidassert2(String s)throwsUnsupportedEncodingException {
byte[] b = s.getBytes("utf-8");
byte[] b2 = fromUCS2(s.toCharArray());
if(b.length == b2.length) {
inti;
for(i =0; i
if(b[i] != b2[i]) {
break;
}
}
if(i == b.length) {
return;
}
}
thrownewRuntimeException("Can not pass assert2 for: "+ s);
}
publicstaticvoidmain(String[] args)throwsException {
assert1("test");
assert1("中文测试");
assert1("A中V文c测d试E");
assert1("\u052CA\u052CBc测");
assert2("test");
assert2("中文测试");
assert2("A中V文c测d试E");
assert2("\u052CA\u052CBc测\u007F\u07FF");
System.out.println("pass");
}
}
java ucs2转utf8_UCS-2和UTF-8的互相转换相关推荐
- java中的字符,字符串,数字之间的转换(亲测)
string 和int之间的转换 string转换成int :Integer.valueOf("12") int转换成string : String.valueOf(12) ch ...
- java中的字符,字符串,数字之间的转换
java中的字符,字符串,数字之间的转换 string 和int之间的转换 string转换成int :Integer.valueOf(" ") int转换成string : St ...
- 一文读懂Java中File类、字节流、字符流、转换流
一文读懂Java中File类.字节流.字符流.转换流 第一章 递归:File类: 1.1:概述 java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建.查找和删除等操作. ...
- Java 图像处理教程(人脸检测,添加水印,图像颜色转换)
Java 图像处理教程(人脸检测,添加水印,图像颜色转换) 文章目录 Java 图像处理教程(人脸检测,添加水印,图像颜色转换) 1:图片的读和写 2:彩色图像转换成灰度图像 3:彩色图像转换成负图像 ...
- java ucs2转utf8_Windows下Unicode(UCS2),UTF8,GBK(GB2312)互转
Windows下提供了两个编码转换函数:WideCharToMultiByte和MultiByteToWideChar. 用它们可实现Unicode(UCS2),UTF8,GBK(GB2312)互转. ...
- java ucs2转utf8_Unicode,UTF8,GB2312,UCS2,GBK之间的转换
Unicode,UTF8,GB2312,UCS2,GBK之间的转换 平时用到的几种编码格式转换.平时用的不是很多.但是在做短信协议的时候,就经常遇到了.这段时间做短信平台接口,总结了几个,也不是很全. ...
- java ucs2转utf8_UCS2转UTF-8方法
前两天工作时需要将UCS2编码转为UTF-8编码在网页显示.网上找了好久没有好方法,后来还是同事给了一个自己的函数,顺利解决问题.把函数贴在这里,愿帮助遇到同样问题的工友们~ /** * UCS2转码 ...
- java ucs2解码_UCS2编码与解码
/*--------------------------------------------------------------*/ // UCS2编码 // 输入: pSrc - 源字符串指针 // ...
- java ucs2解码,短信中的的 UCS2的编码与解码步骤(java)
/** * UCS2解码 * * @param src * UCS2 源串 * @return 解码后的UTF-16BE字符串 */ public static String DecodeUCS2(S ...
最新文章
- 手挽手带你学React:四档(上)一步一步学会react-redux (自己写个Redux)
- Linux 安装 TigerVNC
- 拥抱RxJava(番外篇):关于RxJava的Tips Tricks
- Java IO在Android中应用(三):Apk加固去壳
- 如何将Dictionary绑定到Repeater?
- Oracle序列的建立以及使用
- java中对象的生存期_深入理解Java虚拟机-判断对象是否存活算法与对象引用
- C++ 查看输入流中的下一个字符
- graph slam tutorial :从推导到应用2
- mysql将俩个SQL查询出来的不一样的结果横向拼接成一行数据
- Mysql指定编码导入导出数据
- 区块链+”来了,区块链金融将如何颠覆传统金融
- Echarts中饼状图显示百分比
- PS 图片背景变为透明
- 由内而外全面造就自己
- redis1.2.6 sds.c
- 常见windows字体和MacOS字体分类主要有几种?
- SpringMVC Web实现文件上传下载功能实例解析
- SlideLive网站:提供PPT模板在线播放和免费下载的功能
- Linux驱动01 - Timer