我有一个与数字字符串相关的夫妇列表,其中有22k。 (它是MAC地址供应商列表)。
在我的代码中,我通过前三个字节的MAC地址搜索供应商名称。
我知道,我可以使用字典,甚至可以使用数组,但每次运行程序时都需要初始化字典,但程序只使用少量翻译(项目不到百分之一)在字典中)并且在程序运行时字典的初始化需要花费大量时间。
你能想象其他方法吗?在旧的VB6中,有可能读取二进制文件并查找记录,这对我来说已经足够了,因为我只会加载我实际需要的值。
我更喜欢项目内的解决方案 - 因此没有包含数据的外部文件。我正在尝试使用以下代码: -
Vendors.add("00125A","Microsoft Corporation")
'... this in another 22000 times '
Vendors.add("00124E","XAC AUTOMATION CORP.")
答案 0 :(得分:1)
不确定最适合您的行为应该是什么,或者这实际上对您有什么帮助,但是......
您似乎正在寻找一种方法来搜索和读取结构化文件中的某条记录。
为此,您可以定义一个类来封装记录字段以及访问方法。
这是一个例子。在我的机器上创建,存储22k +记录并在大约20ms内搜索所有记录。 Otoh做100次随机搜索需要3.5秒,显然是因为它总是从开始时开始。进行顺序搜索的速度相当快......
当然,总时间取决于您的机器以及您要寻找和阅读的记录数量。
这是一个包含字节,长整数和字符串的记录类:
class aRecord
{
byte aByte { get; set; }
long aLong { get; set; }
string aString { get; set; }
public aRecord() { }
public aRecord(byte b_, long l_, string s_)
{ aByte = b_; aLong = l_; aString = s_; }
public void writeToStream(BinaryWriter bw )
{
bw.Write(aByte);
bw.Write(aLong);
bw.Write(aString);
}
public void readFromStream(BinaryReader br)
{
aByte = br.ReadByte();
aLong = br.ReadInt64();
aString = br.ReadString();
}
static public aRecord readFromStream(BinaryReader br, int record)
{
int r = 0;
aRecord rec = new aRecord();
br.BaseStream.Position = 0;
while (br.PeekChar() != -1 & r <= record )
{
rec.readFromStream(br);
r++;
}
return rec;
}
static public aRecord readFromStream(BinaryReader br, string search)
{
aRecord rec = new aRecord();
while (br.PeekChar() != -1 )
{
rec.readFromStream(br);
if (rec.aString.Contains(search)) return rec;
}
return null;
}
}
我测试过这样:
Console.WriteLine(DateTime.Now.ToString("ss,ffff") + " init ");
List<aRecord> data = new List<aRecord>();
Random rnd = new Random(9);
int count = 23000;
for (int i = 1000; i < count; i++ )
{
data.Add(new aRecord((byte)(i%128), i, "X" + rnd.Next(13456).ToString()));
}
Console.WriteLine(DateTime.Now.ToString("ss,ffff") + " write ");
string fileName = "D:\\_DataStream.dat";
FileStream sw = new FileStream(fileName, FileMode.Create);
BinaryWriter bw = new BinaryWriter(sw);
foreach(aRecord r in data)
{
r.writeToStream(bw);
}
bw.Flush();
sw.Close();
bw.Close();
FileStream sr = new FileStream(fileName, FileMode.Open);
BinaryReader br = new BinaryReader(sr);
List<aRecord> data2 = new List<aRecord>();
Console.WriteLine(DateTime.Now.ToString("ss,ffff") + " begin search");
for (int i = 0; i < 100; i++)
{
aRecord rec = aRecord.readFromStream(br, "911");
if (rec != null) data2.Add(rec);
}
Console.WriteLine(DateTime.Now.ToString("ss,ffff") + " done. found " + data2.Count);
Console.WriteLine(DateTime.Now.ToString("ss,ffff") + " seek ");
aRecord ar = aRecord.readFromStream(br, 0);
Console.WriteLine(DateTime.Now.ToString("ss,ffff") + " 0 ");
aRecord ar1 = aRecord.readFromStream(br, 1);
Console.WriteLine(DateTime.Now.ToString("ss,ffff") + " 1 ");
aRecord ar2 = aRecord.readFromStream(br, 13000);
Console.WriteLine(DateTime.Now.ToString("ss,ffff") + " 13000 ");
aRecord ar3 = aRecord.readFromStream(br, 23000-1);
Console.WriteLine(DateTime.Now.ToString("ss,ffff") + " 23000 end ");
br.Close();
sr.Close();
您的标题与优化Dictionary
有关。这取决于主要用途:阅读还是写作?如果您在字典中阅读了很多内容,最好创建一个SortedDictionary
。如果你需要创建许多mor条目而不是你期望阅读的正常Dictionary
会更好..
..并且有更多的收集类,但第一件事是找出真正的瓶颈。上述搜索和读取例程不会浪费时间将数据插入Dictionary
,而只是丢弃它们直到找到正确的记录。我还添加了一个搜索方法,在每次点击相同位置后继续。扩展课程以满足您自己的需求非常简单。
27,2208 init
27,2297写
27,2438寻求
27,2438开始搜索
完成了27,3097次。发现3827,3097 0结束
27,3097 1结束
27,3457 13000 end
27,4037 23000结束
答案 1 :(得分:0)
您可以将数据嵌入为资源,然后使用ResourceManager
的实例来检索值。
var rm = new ResourceManager(baseName, assembly);
string vendor = rm.GetString(macAddress);
要创建资源文件(无需将其键入Visual Studio),您可以创建一个可执行文件来读取源文件并从中创建.resources文件:
string path = Path.GetFullPath(Path.Combine(outputPath, "..\\MyData.resources"));
using (IResourceWriter rsxw = new ResourceWriter(path))
{
foreach (var x ...)
{
rsxw.AddResource(x.name, x.value);
}
rsxw.Close();
}
在项目中包含此MyData.resources文件,它将作为资源进行编译。