一、主要作用
实现UTF-8字节序列的读取,转成String字符串;
二、主要思路
1、根据UTF-8每个字节的前缀来确定一个字符的字节组成部分;
2、把属于一个字符的所有连续字节读取,提取关键字节,相加或者属于一个字符的唯一整数;
3、把这个整数强制转成char类型,就获得了字符值;
三、主要代码如下
public class StringUtil{
/**
* 使用UTF-8的方法读取字符串。
*
* @param source
* @return
*/
public static String toStringByUTF8(byte[] source) {
/*
UTF-8的规则如下:
根据前缀,判断这个字符由几个字节组成;x代表字符的二进制序列,依次填入
0xxxxxxx 一个字节,表示ASCII码
110xxxxx 10xxxxxx 前缀为110,代表连续的两个字节,表示一个字符
1110xxxx 10xxxxxx 10xxxxxx 前缀为1110,代表连续的三个字节,表示一个字符
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 前缀为11110,代表连续的四个字节,表示一个字符
*/
// 定义下标变量
int index = 0;
// 定义个数,1代表一个字节,4代表四个字节。
int size = 1;
// 判断是否处理进行字符转换,说明某个字符的所有字节都获取到了。
boolean isEnd = false;
// 存放最终的字符数据
StringBuffer result = new StringBuffer();
// 存放某个字节的二进制码
StringBuffer buffer = new StringBuffer();
while (true) {
// 如果超出范围,跳出循环
if (index >= source.length) {
break;
}
// 转成二进制的字符串形式
String bin = Integer.toBinaryString(source[index] & 0xFF);
// 位数不够8位要左边补零
if (bin.length() < 8) {
String temp = getZeros(8 - bin.length());
bin = temp.concat(bin);
}
// 根据前缀判断类别
if (bin.charAt(0) == '0') {
size = 1;
buffer.append(bin.substring(1));
// 设置可以直接获取
isEnd = true;
} else if (bin.startsWith("110")) {
size = 2;
buffer.append(bin.substring(3));
} else if (bin.startsWith("1110")) {
size = 3;
buffer.append(bin.substring(4));
} else if (bin.startsWith("11110")) {
size = 4;
buffer.append(bin.substring(5));
} else if (bin.startsWith("111110")) {
size = 4;
buffer.append(bin.substring(6));
} else if (bin.startsWith("10")) {
// 添加二进制数据码
buffer.append(bin.substring(2));
size--;
if (size == 1) {
isEnd = true;
}
}
// 判断是否进行转换一次
if (isEnd) {
// 转换成char类型,存入结果缓冲里。
result.append((char) Integer.parseInt(buffer.toString(), 2));
// 清空buffer
buffer.delete(0, buffer.length());
// 设置标志位false
isEnd = false;
}
index++;
}
return result.toString();
}
/**
* 传入字符串,返回它的UTF-8字节流数组
*
* @param str
* @return
*/
public static byte[] getBytesUTF8(String str) {
// 字节数组输出流
ByteArrayOutputStream stream = new ByteArrayOutputStream();
// 定义索引
int index = 0;
// 转换成字符数组
char[] charArray = str.toCharArray();
// 中间变量
char temp = ' ';
// 存放一个字节的二进制码
String bitStr = "";
while (true) {
if (index >= charArray.length){
break;
}
// 获得某个字符
temp = charArray[index];
// 获得二进制字符码
String binaryStr = Integer.toBinaryString(temp);
if (temp >= 0x00 && temp <= 0x7F) {
// 转换成整数,写入字节数组输出流
stream.write(Integer.parseUnsignedInt(binaryStr, 2));
} else if (temp >= 0x80 && temp <= 0x7FF) {
bitStr = formatBinString(binaryStr, 11);
stream.write(Integer.parseUnsignedInt("110" + bitStr.substring(0, 5), 2));
stream.write(Integer.parseUnsignedInt("10" + bitStr.substring(5), 2));
} else if (temp >= 0x800 && temp <= 0xFFFF) {
bitStr = formatBinString(binaryStr, 16);
stream.write(Integer.parseUnsignedInt("1110" + bitStr.substring(0, 4), 2));
stream.write(Integer.parseUnsignedInt("10" + bitStr.substring(4, 10), 2));
stream.write(Integer.parseUnsignedInt("10" + bitStr.substring(10), 2));
} else if (temp >= 0x10000 && temp <= 0x10FFFF) {
bitStr = formatBinString(binaryStr, 21);
stream.write(Integer.parseUnsignedInt("11110" + bitStr.substring(0, 3), 2));
stream.write(Integer.parseUnsignedInt("10" + bitStr.substring(3, 9), 2));
stream.write(Integer.parseUnsignedInt("10" + bitStr.substring(9, 15), 2));
stream.write(Integer.parseUnsignedInt("10" + bitStr.substring(15), 2));
}
index++;
}
// 返回字节数组
return stream.toByteArray();
}
/**
* 格式化字符串:
* <p>
* 如果多余,去掉左边的0;
* 如果没有达到位数,左边加0;
*/
public static String formatBinString(String source, int length) {
String result = "";
if (source.length() == length){
result = source;
} else if (source.length() < length){
// 拼接数字0,返回
result = getZeros(length - source.length()).concat(source);
} else {
// 获得多余的个数
int overflow = source.length() - length;
// 取得子字符串返回
result = source.substring(overflow);
}
return result;
}
/**
* 返回指定位数由0拼接成的字符串
*
* @param count
* @return
*/
public static String getZeros(int count) {
String result = "";
for (int i = 0; i < count; i++) {
result += "0";
}
return result;
}
/**
* 按照Unicode的格式读取一个字符,占用两个字节
*
* @param source
* @return
*/
private static char toUnicodeChar(byte[] source) {
int length = source.length;
System.out.println("长度:" + length);
int result = 0;
int temp = 0;
for (int k = length - 1; k >= 0; k--){
temp = (source[k] & 0xFF);
temp = temp << (8 * k);
result = result + temp;
}
System.out.println(source[0] & 0xFF);
System.out.println(source[1] & 0xFF);
System.out.println(source[2] & 0xFF);
System.out.println(source[3] & 0xFF);
return (char)result;
}
}