【发布时间】:2016-11-15 21:43:25
【问题描述】:
我已使用已接受的答案 here“手动”将 unicode 转换为 UTF-8 代码单元。问题是我需要将生成的 UTF-8 包含在字节数组中。如何通过尽可能使用移位操作从十六进制转换为 uft-8 来做到这一点?
我已有的代码如下:
public static void main(String[] args)
throws UnsupportedEncodingException, CharacterCodingException {
String st = "ñ";
for (int i = 0; i < st.length(); i++) {
int unicode = st.charAt(i);
codepointToUTF8(unicode);
}
}
public static byte[] codepointToUTF8(int codepoint) {
byte[] hb = codepointToHexa(codepoint);
byte[] binaryUtf8 = null;
if (codepoint <= 0x7F) {
binaryUtf8 = parseRange(hb, 8);
} else if (codepoint <= 0x7FF) {
binaryUtf8 = parseRange(hb, 16);
} else if (codepoint <= 0xFFFF) {
binaryUtf8 = parseRange(hb, 24);
} else if (codepoint <= 0x1FFFFF) {
binaryUtf8 = parseRange(hb, 32);
}
byte[] utf8Codeunits = new byte[hexStr.length()];
for (int i = 0; i < hexStr.length(); i++) {
utf8Codeunits[i] = (byte) hexStr.charAt(i);
System.out.println(utf8Codeunits[i]); // prints 99 51 98 49,
// which is the same as c3b1, the UTF-8 for ñ
}
return binaryUtf8;
}
public static byte[] codepointToHexa(int codepoint) {
int n = codepoint;
int m;
List<Byte> list = new ArrayList<>();
while (n >= 16) {
m = n % 16;
n = n / 16;
list.add((byte) m);
}
list.add((byte) n);
byte[] bytes = new byte[list.size()];
for (int i = list.size() - 1; i >= 0; i--) {
bytes[list.size() - i - 1] = list.get(i);
}
return bytes;
}
private static byte[] parseRange(byte[] hb, int length) {
byte[] binarybyte = new byte[length];
boolean[] filled = new boolean[length];
int index = 0;
if (length == 8) {
binarybyte[0] = 0;
filled[0] = true;
} else {
int cont = 0;
while (cont < length / 8) {
filled[index] = true;
binarybyte[index++] = 1;
cont++;
}
binarybyte[index] = 0;
filled[index] = true;
index = 8;
while (index < length) {
filled[index] = true;
binarybyte[index++] = 1;
binarybyte[index] = 0;
filled[index] = true;
index += 7;
}
}
byte[] hbbinary = convertHexaArrayToBinaryArray(hb);
int hbindex = hbbinary.length - 1;
for (int i = length - 1; i >= 0; i--) {
if (!filled[i] && hbindex >= 0) {
// we fill it and advance the iterator
binarybyte[i] = hbbinary[hbindex];
hbindex--;
filled[i] = true;
} else if (!filled[i]) {
binarybyte[i] = 0;
filled[i] = true;
}
}
return binarybyte;
}
private static byte[] convertHexaArrayToBinaryArray(byte[] hb) {
byte[] binaryArray = new byte[hb.length * 4];
String aux = "";
for (int i = 0; i < hb.length; i++) {
aux = Integer.toBinaryString(hb[i]);
int length = aux.length();
// toBinaryString doesn't return a 4 bit string, so we fill it with 0s
// if length is not a multiple of 4
while (length % 4 != 0) {
length++;
aux = "0" + aux;
}
for (int j = 0; j < aux.length(); j++) {
binaryArray[i * 4 + j] = (byte) (aux.charAt(j) - '0');
}
}
return binaryArray;
}
我不知道如何正确处理字节,所以我知道我所做的事情可能是错误的。
【问题讨论】:
-
这是作业吗?您可以使用
String.getBytes("UTF-8")验证结果。维基百科将显示位模式 10xxxxxx 等。掩蔽和转移不是魔法。 -
不,这不是家庭作业。我需要用于个人项目的转换器,并且我希望它高效。我知道位模式,因为它们在我引用的链接中。但我不知道要改变什么(或什么时候做)才能得到想要的结果。
-
...是的,它的功课。想要比经过验证、测试和现成的 JRE 方法更“高效”有点……多余,而且闻起来非常像运动。可能是大学考试 - IT 学生被告知,如今重新发明轮子是一件很酷的事情......这对他们的职业生涯来说是可怕的,但对于深入了解实现细节的无用深度知识确实会产生奇迹。
-
两年前我大学毕业了。你们都错了,对不起。我只想通过自己编码来了解事物的工作原理。否则,我不会学习任何有关编码的知识,只需使用现有的库即可。但现在看来,努力学习已经被视为作弊了。
-
不,“作弊”这个词在上下文中甚至没有意义——从字面上重新发明轮子不是为了一个单一的目的,没有要获得的知识,只有在无用的主题上的经验。如果您想获得知识,您需要阅读论文、测试参考实现、组装大量库并正确使用它们或开始 IT 研究生涯。轮子不会教你任何东西,它只是做它的工作——你将无法理解轮子背后的物理原理,因为你拆开了一两个,但你可以开始发明一个矩形轮子
标签: java unicode encoding utf-8 byte-shifting