为什么,当我将 INT 值转换为字节和 ASCII 并返回时,我得到另一个值?
例子:
var asciiStr = new string(Encoding.ASCII.GetChars(BitConverter.GetBytes(2000)));
var intVal = BitConverter.ToInt32(Encoding.ASCII.GetBytes(asciiStr), 0);
Console.WriteLine(intVal);
// Result: 1855
Run Code Online (Sandbox Code Playgroud)
Joe*_*ell 14
ASCII 只有 7 位 -127不支持上述代码点。不支持的字符将?根据以下文档Encoding.ASCII转换为:
此属性返回的 ASCIIEncoding 对象可能没有适合您的应用程序的行为。它使用替换回退来替换它无法编码的每个字符串以及它无法使用问号 (“?”) 字符解码的每个字节。
所以2000十进制=D0 07 00 00十六进制(小端)= [unsupported character] [BEL character] [NUL character] [NUL character]= ? [BEL character] [NUL character] [NUL character]=3F 07 00 00十六进制(小端)=1855小数。
TL;DR:一切都很好。但你是字符替换的受害者。
我们从2000. 首先让我们承认,这个数字可以用十六进制表示为0x000007d0。
BitConverter.GetBytes(2000)是一个 4 个字节的数组,因为 2000 是一个 32 位整数文字。所以 32 位整数表示,以小端(最低有效字节在前),由以下字节序列给出{ 0xd0, 0x07, 0x00, 0x00 }。在十进制中,这些相同的字节是{ 208, 7, 0, 0 }
哦哦!问题。 这就是事情可能发生意外转折的地方。
您要求系统将这些字节解释为 ASCII 编码数据。问题是 ASCII 使用 0-127 之间的代码。值为 208 ( 0xd0)的字节不对应于任何可被 ASCII 编码的字符。那么实际上会发生什么呢?
解码 ASCII 时,如果遇到超出 0-127 范围的字节,则将该字节解码为替换字符并移至下一个字节。这个替换字符是一个问号?。所以你从 Encoding.ASCII.GetChars 得到的 4 个字符是?, BEL (bell), NUL (null) 和NUL (null)。
BEL是带有代码 7 的字符的 ASCII 名称,传统上,当出现在有能力的终端上时会引起蜂鸣声。NUL(代码 0)是一个空字符,传统上用于表示字符串的结尾。
现在您从该字符数组创建一个字符串。在 C# 中,字符串完全能够表示字符串主体内的 NUL 字符,因此您的字符串中将包含两个 NUL 字符。它们可以在 C# 字符串文字中用 表示"\0",以防您想自己尝试。AC# 字符串文字表示您将拥有的字符串 您"?\a\0\0" 知道 BEL 字符可以用转义序列 表示\a吗?很多人没有。
现在你开始反向旅程。您的字符串完全由 ASCII 范围内的字符组成。问号的编码是代码 63 (0x3F)。BEL 是 7,NUL 是 0。所以字节是{ 0x3f, 0x07, 0x00, 0x00 }. 惊讶?好吧,您现在正在编码一个问号,之前您提供了一个无法用 ASCII 编码表示的 208 (0xd0) 字节。
将这四个字节转换回 32 位整数给出整数0x0000073f,十进制为1855。