C#中的位操作
比较基础的东西,平时用的不多,真到碰到时却不会用了,下面是整理的一些资料
int类型即Int32, 由4个字节32位表示,高第31位(编号从零开始)用来表示正负,1为负数,0为正数 (左表示高位,右表示低)
int 类型的负数是采用补码来表示的,即在对应的int类型正数上按位求反后再加1
比方计算-1,其正数为 0000000...001(31个零跟一个1) 那么按位求反后应该是 111111111....10 ,再加1的结果是11111111...111(32个1).
long类型跟int类似,只不过long由8字节64位表示
数据转换常用代码
//将16进制数0XFFFFFFFF转换为整数(Int32)
MessageBox.Show( Convert.ToInt32("FFFFFFFF", 16).ToString()); //显示 -1
//将2进制数11111111转换为整数(Int32),注意11111111 等效于 0000...00011111111 (前面24个零)
MessageBox.Show(Convert.ToInt32("11111111",2).ToString());// 显示 255
//将整数-1转换成2进制字符串
MessageBox.Show(Convert.ToString(-1, 2)); // -1的二进制表示,显示11111....11 (32个1)
//将整数-1转换成16进制字符串
MessageBox.Show(Convert.ToString(-1, 16)); // -1的16进制表示,显示FFFFFFFF
使用BitConverter
byte[] bytes = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF,0 ,0};
//取bytes数据的第0个到第3个元素(int类型有4个字节) ,转化成整数
MessageBox.Show( BitConverter.ToInt32(bytes, 0).ToString()); //显示 -1;
//将byte[] 数组表示成十六进制字符串序列,各元素转化后用 "-"连接,顺序不变
MessageBox.Show( BitConverter.ToString(bytes)); //显示 FF-FF-FF-FF-0-0
//获取10(Int32)的字节数组
byte[] arr=BitConverter.GetBytes(10); //生成的数组为 {10,0,0,0}
MessageBox.Show(BintConverter.ToString(arr)); //显示为0A-0-0-0;
这里注意10的Int32内存表示方法是 00-00-00-0A(高字节左边低字节在右边) ,而上面的是通过BinConverter转化后是高字节在右边低字节在左边.
使用位操作
在开发一些带权限控制的功能时我们有可能用到位操作,
比方系统中有一些资源,每个资源对应一组操作,假设有8种操作
这个时候你就可以设计这么一张表
资源用户操作表(用户名,资源号,操作类型)
一些数据:
tools 1, 1
tools 2, 2
tools 1 , 3
alsve 3, 1
alsve 1,2
在上面我们用数字1~8表示8种操作,显然如果一个用户对某一资源拥有全部权限的话就需要8条记录来表示,如果用户达到几十万级别时这个表的数据量将会很庞大.
改用位来表示操作
资源用户操作表(用户名,资源号,操作数)
这里我们使用了操作数,他是int类型的整数 我们使用其低8位来表示某用户对某资源拥有操作,对应位为1则表示有相应权限,为零则表示没有.
在上面的规则下我们需要用到以下操作
1.判断某一位是否为1 即用户是否拥有某资源的某一操作,
bool表达式 (操作数 & (1<< 位置)) > 0;
2.设置某一位为1,即将某一资源的某一操作分配给用户
操作数=操作数 | (1<<位置);
3. 设置某一位为0,即将用户对某一资源的某一操作取消
操作数=操作数 & (~(1<<位置)); //移位后,按位求反,再与操作数做与操作
一些实现细节
用户登录后一次性将用户的资源操作数据加载到 Hashtable里(包括用户属于的角色分配的资源操作数据)
代码类似如下:
foreach(...){
hash.Add("资源号","操作数") ;
}
当然用户会属于一些角色的,而给角色分配的资源操作可能跟给用户分配的资源操作重叠,
这个时候就需要将2者合并, 修改后的代码类似如下
foreach(....){
if (hash.ContainsKey("资源号"))
{
hash["资源号"] = (int)hash["资源号"] | "操作数";
}
else
{
hash.Add("资源号", "操作数");
}
}
Hashtable可以方便的序列化,序列化后的数据可以保存在 Session(使用SQL保存Session)或者保存在加密的ViewState里面,当然同样可以把ViewState保存到SQL服务器里,不过,使用SQL Session 比较方便