本文主要目的,解决多选项数据存储问题,如选择了A和B 2个选项,数据该怎么存
经过
对于很多办公协作软件,多选的数据存储格式对于后期的拓展尤为重要。
去年,因为公司的业务需求,开发了一套自定义控件,包括文本,单选多选,公式,附件等控件一共20多种。但是因为天真选择类控件用了10进制来存储,用了2的n次幂这种方式,选择的存储介质是Mongodb,因为Mongodb的$bitsAnySet对于筛选的支持尤为的强大。
然而上线后,因为客户的使用会涉及大量的选项录入,倒置double类型10进制精度的丢失,八阿哥真是拦都拦不住,也因为工期紧,一直都没去想补偿方案填补这个漏洞。近期因为新模块对控件的使用,填补这个漏洞又搬上了议程,经过大神的指点以及自己的摸索,已经完成了替换的方案,设计方式如下:
- 后端数据库mongodb存binary 下 bindata(0,"")二进制格式
- 前端暴露为二进制字符串,如 "101010101"
具体mongo查询逻辑
https://docs.mongodb.com/manual/reference/operator/query/bitsAnySet/
C#=>mongodb bindata格式
https://jira.mongodb.org/browse/CSHARP-437
下面为C#实现的各个进制互转等帮助类方法
/// <summary>
/// 二进制字符串转byte[]
/// </summary>
/// <param name="binaryStr"></param>
/// <returns></returns>
public static byte[] ConvertBinaryStringToBytes(string binaryStr)
{
binaryStr = binaryStr.Replace("-", string.Empty);
binaryStr = BinaryLengthAppendTo8(binaryStr);
byte[] resultantArray = new byte[binaryStr.Length / 8];
for (int i = 0; i < resultantArray.Length; i++)
{
var str = binaryStr.Substring(i * 8, 8);
resultantArray[i] = Convert.ToByte(str, 2);
}
return resultantArray;
}
/// <summary>
/// 二进制字符串转base64
/// </summary>
/// <param name="binaryStr"></param>
/// <returns></returns>
public static string ConvertBinaryStringToBase64(string binaryStr)
{
var byteArr = ConvertBinaryStringToByteArr(binaryStr);
return Convert.ToBase64String(byteArr);
}
/// <summary>
/// 10进制转二进制字符串("100010010"格式)
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
public static string ConvertDoubleToString(double num)
{
List<string> binary = new List<string>();
while (num > 0)
{
double tmp = num;
num = Math.Floor(tmp / 2);
binary.Add((tmp % 2).ToString());
}
binary.Reverse();
return string.Join(string.Empty, binary);
}
/// <summary>
/// btye[]转二进制字符串
/// </summary>
/// <param name="bindata"></param>
/// <returns></returns>
public static string ConvertBinaryToString(byte[] bindata)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bindata.Length; i++)
{
string hv = Convert.ToString(bindata[i], 2);
hv = BinaryLengthAppendTo8(hv);
sb.Append(hv);
}
return sb.ToString();
}
public static byte[] ConvertDoubleToBytes(double num)
{
return ConvertBinaryStringToByteArr(ConvertDoubleToString(num));
}
/// <summary>
/// 转换bindata到十进制double(强转溢出后返回-1)
/// </summary>
/// <param name="bindata"></param>
/// <returns></returns>
public static double ConvertBinaryToDouble(byte[] bindata)
{
string binary = ConvertBinaryToString(bindata);
return ConvertBinaryStrToDouble(binary);
}
/// <summary>
/// 转换"10101010"到十进制double(强转溢出后返回-1)
/// </summary>
/// <param name="binaryStr"></param>
/// <returns></returns>
public static double ConvertBinaryStrToDouble(string binaryStr)
{
try
{
int binLen = binaryStr.Length;
double sum = 0;
for (int i = 0; i < binLen; i++)
{
if (binaryStr[i] == '1')
{
sum += Math.Pow(2, binLen - i - 1);
}
}
if (double.IsInfinity(sum))
{
throw new Exception("溢出");
}
return sum;
}
catch
{
return -1;
}
}
private static string BinaryLengthAppendTo8(string binaryStr)
{
int m = binaryStr.Length % 8;
if (m != 0)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 8 - m; i++)
{
sb.Append("0");
}
binaryStr = sb.ToString() + binaryStr;
}
return binaryStr;
}
网友评论