我认为UCS-2与ISO-8859-1相同
rawData = new byte[data.length()];
for(int i=0; i<data.length(); i++) {
rawData[i] = (byte)(data.charAt(i) & 0xff);
}
这似乎是错误的。为什么上述代码不等同于data.getBytes("ISO8859_1")
?我在Android上。
事实上,事实证明我的一些角色是0xf700 & (byte)
。出于某种原因,当您使用XMLHttpRequest
和Charset: x-user-defined
获取二进制文件时会发生这种情况。转换为latin1
时,这些字符会变为?
(问号)。
答案 0 :(得分:3)
每个Android documentation:
未指定此字符串无法在指定的字符集中表示的行为。
实际上,此调用最终会作为采用显式Charset
的变体,它会将某些替换序列替换为不可翻译的字符。在Sun JDK中,这是一个单字节值64('?')。
但是,在您对早期答案的评论中,您保证字符串中没有大于'0xFF'的字符值,那么您做错了。 ISO-8859-1是UCS-2 / UTF-16的适当子集。
答案 1 :(得分:2)
原因已经由parsifal的回答解释了。为了完整性,这里的代码相当于data.getBytes("ISO-8859-1")
(假设字符串是纯UCS-2字符串,没有代理项对):
byte[] rawdata = new byte[data.length()];
for(int i = 0; i < data.length; i++) {
char c = data.charAt(i);
if (c > 255) {
rawData[i] = (byte)'?';
}
else {
rawData[i] = (byte)c;
}
}
对于代理人(例如真正的UTF-16),它会变得更复杂:
byte[] rawData = new byte[data.length()];
int j = 0;
for(int i = 0; i < data.length; i++, j++) {
int c = data.codePointAt(i);
if(c < 0x100) {
rawData[j] = (byte)c;
}
else {
rawData[j] = (byte)'?';
if(c >= 0x10000) {
// surrogate pair
i++;
}
}
}
if(j < rawData.length) {
rawData = Arrays.copyOf(rawData, j);
}
或者,只使用charAt()
:
byte[] rawData = new byte[data.length()];
int j = 0;
for(int i = 0; i < data.length; i++, j++) {
char c = data.charAt(i);
if(c < 0x100) {
rawData[j] = (byte)c;
}
else {
rawData[j] = (byte)'?';
if(Character.isHighSurrogate(c) && Character.isLowSurrogate(data.charAt(i+1))) {
// surrogate pair
i++;
}
}
}
if(j < rawData.length) {
rawData = Arrays.copyOf(rawData, j);
}