【发布时间】:2017-04-01 08:28:34
【问题描述】:
我希望从 Stream 或 BinaryReader 读取下一个 UTF8 字符。不起作用的事情:
BinaryReader::ReadChar -- 这将抛出一个 3 或 4 字节的字符。由于它返回的是一个两字节的结构,所以它别无选择。
BinaryReader::ReadChars -- 如果您要求它读取 1 个字符并且遇到 3 或 4 字节字符,则会抛出此错误。如果您要求它读取超过 1 个字符,它将读取多个字符。
StreamReader::Read -- 这需要知道要读取多少字节,但 UTF8 字符中的字节数是可变的。
我的代码似乎可以工作:
private char[] ReadUTF8Char(Stream s)
{
byte[] bytes = new byte[4];
var enc = new UTF8Encoding(false, true);
if (1 != s.Read(bytes, 0, 1))
return null;
if (bytes[0] <= 0x7F) //Single byte character
{
return enc.GetChars(bytes, 0, 1);
}
else
{
var remainingBytes =
((bytes[0] & 240) == 240) ? 3 : (
((bytes[0] & 224) == 224) ? 2 : (
((bytes[0] & 192) == 192) ? 1 : -1
));
if (remainingBytes == -1)
return null;
s.Read(bytes, 1, remainingBytes);
return enc.GetChars(bytes, 0, remainingBytes + 1);
}
}
显然,这有点混乱,而且有点特定于 UTF8。对于这个问题,是否有更优雅、更少定制、更易于阅读的解决方案?
【问题讨论】:
-
问题可能重复,但该答案不起作用。具体来说,它不处理代理对。我尝试修改它以使用 2 元素 char 缓冲区,但这只是导致了不同的问题。但是,除了代理对之外,它工作正常。
-
酷,我不能 100% 确定这是否是同一件事,但我认为其中可能包含一些有用的信息。
-
这是一个很好的发现——我的搜索没有找到它。可悲的是,“有什么可行的方法,但没有我目前的解决方案那么难看”这个问题就成立了。