使用BitConverter.GetBytes转换double到byte[]中,得到的数据怎么理解

来源:互联网 发布:java 对文件md5加密 编辑:程序博客网 时间:2024/06/03 19:24

一.获得用户输入的密钥

我这里的讨论使用的平台C# 。
我原本的目的是为了对一组byte[]进行简单的异或加密,而密钥就是从用户输入而来。那么通过何种控件何种方式获得用户的输入呢?

1.方式一,Textbox

第一种就是直接使用Textbox接收用户输入的string,然后使用Encoding的GetBytes[]方法获得byte[]密钥数组。这种的优点是很直观,缺点是用户并不知道最终的密钥Byte[]的内容是什么;

2.方式二,NumericUpAndDown

对应的第二种方式就是,让用户直接输入byte[],那么可以使用数字控件,并且将属性Hex打开,那么用户的输入就会是16进制,然后我们只要将16进制数转换为byte[]就好了,使用的就是BitConverter.GetBytes函数。这里有个问题:

1).密钥byte[]的数组大小问题

众所周知,BitConverter.GetBytes获得的数组大小与填入的参数是什么类型有关。如果是对int GetBytes(),那么数组大小就是4,因为int就是4字节;如果对short ,当然就是2喽。所以问题来了。当用户比如输入了F时,我们如何得知用户想要的密钥数组大小是多少?
解决办法当然是,直接判断数据的极值,比如F明显是一个字节可以搞定的,那么数组大小就是1,7FFF数组大小就是short可以搞定的,那么(short st = (short)NumericUpAndDown.value; byte[] bs = System.BitConverter.GetBytes(st))转换出来的数组大小是2。题外话,为什么我要举个7fff的例子呢,因为对于int16(short)来说,他的正数最大值就是 2的31次方 - 1,就是7FFF了。如果再大一个数,比如到了8000,再想把这个输入的value转换为short就要报错了。
升级解决办法上面这种方式略显麻烦,还有直接的就是直接以最大的数据类型double来转换,转换出来后,把高位的0的byte去掉就好了。当然这种方式得得到用户同意。以为这种方式处理后的byte[]的个数是不可控的。(高手肯定已经发现我的思路有问题了,莫见笑,后面详谈

2).转换double为byte[]时 遇到的懵逼问题

我本意是把用户输入的0xFAADCEAE 转换为 byte[]数组的,那么转换出来的按理应该是
byte[0] AE
byte[1] CE
byte[2] AD
byte[3] FA
byte[4] 0
byte[5] 0
byte[6] 0
byte[7] 0
结果我得到了这么个东西:
byte[0] OCT: 000 HEX: 0
byte[1] OCT: 000 HEX: 0
byte[2] OCT: 192 HEX: c0
byte[3] OCT: 213 HEX: d5
byte[4] OCT: 185 HEX: b9
byte[5] OCT: 085 HEX: 55
byte[6] OCT: 239 HEX: ef
byte[7] OCT: 065 HEX: 41
和我的预期严重不符。于是我做了个简单的测试,输入1,进行了尝试,得到了下面的值
byte[0] OCT: 000 HEX: 0
byte[1] OCT: 000 HEX: 0
byte[2] OCT: 000 HEX: 0
byte[3] OCT: 000 HEX: 0
byte[4] OCT: 000 HEX: 0
byte[5] OCT: 000 HEX: 0
byte[6] OCT: 240 HEX: f0
byte[7] OCT: 063 HEX: 3f
一个1,怎么会有一个高位如此之大的数?
原因就是,我把double是什么东西给忘了!
double是双精度浮点数是浮点数啊,怎么可能是一般的表现形式,明显有什么符号位啊、指数啊、尾数啊!至此,这么个奇怪的byte[]已经水落石出了,为了不辜负大学老师的辛勤,我把课本拾起来,接下来回忆下一个简单的1是怎么变成这么个样子的:
double数据解析
请参考double数据格式:
double数据格式

所以使用double是不正确的,应该使用Int64,才能达到我们的目的。

三.方式三,自定义输入

我使用了最直观的方式,就是还是用Textbox让用户输入16进制形式的若干位密钥。然后用户输入了几位,那么我就存储几位。部分参考代码见下面:

        private void textBox_Key_TextChanged(object sender, EventArgs e)        {            lock (this)            {                string value = textBox_Key.Text;                if (value == "")                {                    textBox_Key.Text = _lastKeyValueStr;                }                //检测输入是否合法,不合法则恢复之前的合法值                if (!CheckHexValue(value))                {                    textBox_Key.Text = _lastKeyValueStr;                }                _lastKeyValueStr = textBox_Key.Text;                List<byte> byteList = new List<byte>();                int i = _lastKeyValueStr.Length - 1;                //每两个16进制数就组成了一个byte,所以两个十六进制数,联合起来进行解析                while (i - 1 >= 0)                {                    byte b = byte.Parse(_lastKeyValueStr[i - 1] + "" + _lastKeyValueStr[i], System.Globalization.NumberStyles.HexNumber);                    byteList.Add(b);                    i -= 2;                }                //若数据为奇数,必定剩一个16进制数(而且这个16进制数已经是最高位了,也就是说遇到0xABC这种情况,我会解析成byte[0]:0A byte[1]:BC)单独处理                if (i == 0)                {                    byte b = byte.Parse(_lastKeyValueStr[i].ToString(), System.Globalization.NumberStyles.HexNumber);                    byteList.Add(b);                }                //之所以进行翻转,是因为我上面是倒着加入到List中的,数据反了,需要翻转回来。                byteList.Reverse();                _key = byteList.ToArray();            }        }
0 0