Joh*_*ant 4 .net string performance
我正在使用VB.NET处理一个长固定长度的记录.最简单的选项似乎是将整个记录加载到一个字符串中,并使用Substring按位置和长度访问字段.但似乎在每个调用中都会在Substring方法中进行一些冗余处理.这让我想知道使用基于流或阵列的方法是否可以获得更好的结果.
内容以包含UTF8字符数据的字节数组开始.我想到的其他几种方法如下所示.
这绝对是不成熟的优化; 子串方法即使慢几毫秒也可以完全接受.但我想在编码之前我会问,只是为了看看是否有人能想到使用其他方法之一的理由.
子字符串的主要成本是将子字符串切换为新字符串.使用Reflector你可以看到:
private unsafe string InternalSubString(int startIndex, int length, bool fAlwaysCopy)
{
if (((startIndex == 0) && (length == this.Length)) && !fAlwaysCopy)
{
return this;
}
string str = FastAllocateString(length);
fixed (char* chRef = &str.m_firstChar)
{
fixed (char* chRef2 = &this.m_firstChar)
{
wstrcpy(chRef, chRef2 + startIndex, length);
}
}
return str;
}
Run Code Online (Sandbox Code Playgroud)
现在到达那里(注意事实并非如此Substring()),它必须经历5次长度检查等.
如果您多次引用相同的子字符串,则可能值得将所有内容拉出一次并丢弃巨型字符串.您将在阵列中产生开销以存储所有这些子串.
如果它通常是"一次性"访问,那么Substring它,否则考虑分区.也许System.Data.DataTable会有用吗?如果您正在进行多次访问并解析为其他数据类型,那么DataTable对我来说看起来更具吸引力.如果您一次只需要一条记录在内存中,则a Dictionary<string,object>应该足以容纳一条记录(字段名称必须是唯一的).
或者,您可以编写一个自定义的泛型类来为您处理固定长度的记录读取.指示每个字段的起始索引和字段的类型.字段的长度由下一个字段的开头推断(例外是可以从总记录长度推断出的最后一个字段).的类型可以被自动转换使用的喜欢int.Parse(),double.Parse(),bool.Parse()等.
RecordParser r = new RecordParser();
r.AddField("Name", 0, typeof(string));
r.AddField("Age", 48, typeof(int));
r.AddField("SystemId", 58, typeof(Guid));
r.RecordLength(80);
Dictionary<string, object> data = r.Parse(recordString);
Run Code Online (Sandbox Code Playgroud)
如果反射适合你的想象:
[RecordLength(80)]
public class MyRecord
{
[RecordFieldOffset(0)]
string Name;
[RecordFieldOffset(48)]
int Age;
[RecordFieldOffset(58)]
Guid Systemid;
}
Run Code Online (Sandbox Code Playgroud)
只需运行属性,您就可以PropertyInfo.PropertyType了解如何处理记录中的子字符串; 你可以从属性中提取偏移量和总长度; 并使用填充的数据返回类的实例.从本质上讲,您可以使用反射来提取信息,以便从我之前的建议中调用RecordParser.AddField()和RecordLength().
然后将它全部包装成一个整洁的小小的,没有大惊小怪的课程:
RecordParser<MyRecord> r = new RecordParser<MyRecord>();
MyRecord data = r.Parse(recordString);
Run Code Online (Sandbox Code Playgroud)
甚至可以调用r.EnumerateFile("path\to\file")并使用yield return枚举语法来解析记录
RecordParser<MyRecord> r = new RecordParser<MyRecord>();
foreach (MyRecord data in r.EnumerateFile("foo.dat"))
{
// Do stuff with record
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3827 次 |
| 最近记录: |