给定一个字节流(代表字符)和该流的编码,我如何获得字符的代码点?
InputStreamReader r = new InputStreamReader(bla, Charset.forName("UTF-8"));
int whatIsThis = r.read();
上面的代码段中的read()返回了什么?它是unicode代码点吗?
最佳答案
Reader.read()
返回的值可以强制转换为char
或-1(如果没有更多数据可用)。char
是(隐式)UTF-16BE编码中的16位代码单元。此编码可以用单个char
表示基本的多语言平面字符。 supplementary range用两个char
序列表示。Character
类型包含用于将UTF-16代码单元转换为Unicode代码点的方法:
当您从isHighSurrogate传递两个连续值时,需要两个char
的代码点将满足isLowSurrogate和sequence。 codePointAt方法可用于从代码单元序列中提取代码点。从代码点到UTF-16代码单元,都有类似的工作方法。
代码点流阅读器的示例实现:
import java.io.*;
public class CodePointReader implements Closeable {
private final Reader charSource;
private int codeUnit;
public CodePointReader(Reader charSource) throws IOException {
this.charSource = charSource;
codeUnit = charSource.read();
}
public boolean hasNext() { return codeUnit != -1; }
public int nextCodePoint() throws IOException {
try {
char high = (char) codeUnit;
if (Character.isHighSurrogate(high)) {
int next = charSource.read();
if (next == -1) { throw new IOException("malformed character"); }
char low = (char) next;
if(!Character.isLowSurrogate(low)) {
throw new IOException("malformed sequence");
}
return Character.toCodePoint(high, low);
} else {
return codeUnit;
}
} finally {
codeUnit = charSource.read();
}
}
public void close() throws IOException { charSource.close(); }
}