从文件中获取可变子字符串长度的最快方法 (C#)
Fastest way to get variable substring lengths from file (C#)
我有一个文本文件,其中包含需要提取的值,每个值的长度都是可变的。每个变量的长度存储在List<int>
中,如果有更有效的方法,可以更改。
问题:给定 List<int>
长度,将可变长度子字符串放入 DataTable
的最快方法是什么?
示例文本文件内容:
Field1ValueField2ValueIsLongerField3Field4IsExtremelyLongField5IsProbablyTheLongestFieldOfThemAll
A1201605172B160349150816431572C16584D31601346427946121346E674306102966595346438476174959205395664
示例List<int>
:
11, 19, 6, 21, 40
示例输出 DataTable
:
Field 1
Field 2
Field 3
Field 4
Field 5
Field1Value
Field2ValueIsLonger
Field3
Field4IsExtremelyLong
Field5IsProbablyTheLongestFieldOfThemAll
A1201605172
B160349150816431572
C16584
D31601346427946121346
E674306102966595346438476174959205395664
字段值没有模式,可以是任何字母数字值,并且只能通过长度列表获取字段值。
我的方法如下:
List<int> lengths = new() { 11, 19, 6, 21, 40};
DataTable dataTable = new();
//Add Columns for each field
foreach (int i in lengths)
{
dataTable.Columns.Add();
}
//Read file and get fields
using (StreamReader streamReader = new(fileName))
{
string line; //temp
while ((line = streamReader.ReadLine()) != null)
{
//Create new row each time we see a new line in the text file
DataRow dataRow = dataTable.NewRow();
//Temp counter for starting index of substring
int tempCounter = 0;
//Enumerate through variable lengths
foreach (int i in lengths)
{
//Set the value for tat cell
dataRow[lengths.IndexOf(i)] = line.Substring(tempCounter, i);
//Add the length of the current field
tempCounter += i;
}
//Add Row to DataTable
dataTable.Rows.Add(dataRow);
}
}
是否有更高效(时间 and/or 记忆)的方式来完成这个任务?
你是在生成那个输入字符串还是那个长度数组?
如果是:
- 保存每个第N个字段起始字符的索引(如果你已经有length-array,那么你也可以建立一个start-array)
- 然后在解码时,使用多个线程一次解析多个索引点并将它们连接到目标列表或数组(imo 数组必须更快,因为你有总数的字段)
如果没有:
- 将遇到的每个字段开始推入队列(带有字段索引)并直接跳转到下一个字段
- 由其他线程从队列中异步弹出元素,并根据它们的索引将它们放入列表中(如果知道总长度,数组可能会更好)
因为当您在同一个循环中同时进行提取和解析时,提取吞吐量会下降。因此,您应该将工作卸载到其他线程,也许一次使用 N 个字段以容忍 multi-threading 同步延迟。
如果 single-thread 提取比 multi-thread 解析太慢,那么您可以尝试矢量化提取。一次启动 128 个字符采样器,检查它们是否找到前缀代码并在它们之间进行归约以找到其中的第一个前缀(如果找到多个)。
我有一个文本文件,其中包含需要提取的值,每个值的长度都是可变的。每个变量的长度存储在List<int>
中,如果有更有效的方法,可以更改。
问题:给定 List<int>
长度,将可变长度子字符串放入 DataTable
的最快方法是什么?
示例文本文件内容:
Field1ValueField2ValueIsLongerField3Field4IsExtremelyLongField5IsProbablyTheLongestFieldOfThemAll
A1201605172B160349150816431572C16584D31601346427946121346E674306102966595346438476174959205395664
示例List<int>
:
11, 19, 6, 21, 40
示例输出 DataTable
:
Field 1 | Field 2 | Field 3 | Field 4 | Field 5 |
---|---|---|---|---|
Field1Value | Field2ValueIsLonger | Field3 | Field4IsExtremelyLong | Field5IsProbablyTheLongestFieldOfThemAll |
A1201605172 | B160349150816431572 | C16584 | D31601346427946121346 | E674306102966595346438476174959205395664 |
字段值没有模式,可以是任何字母数字值,并且只能通过长度列表获取字段值。
我的方法如下:
List<int> lengths = new() { 11, 19, 6, 21, 40};
DataTable dataTable = new();
//Add Columns for each field
foreach (int i in lengths)
{
dataTable.Columns.Add();
}
//Read file and get fields
using (StreamReader streamReader = new(fileName))
{
string line; //temp
while ((line = streamReader.ReadLine()) != null)
{
//Create new row each time we see a new line in the text file
DataRow dataRow = dataTable.NewRow();
//Temp counter for starting index of substring
int tempCounter = 0;
//Enumerate through variable lengths
foreach (int i in lengths)
{
//Set the value for tat cell
dataRow[lengths.IndexOf(i)] = line.Substring(tempCounter, i);
//Add the length of the current field
tempCounter += i;
}
//Add Row to DataTable
dataTable.Rows.Add(dataRow);
}
}
是否有更高效(时间 and/or 记忆)的方式来完成这个任务?
你是在生成那个输入字符串还是那个长度数组?
如果是:
- 保存每个第N个字段起始字符的索引(如果你已经有length-array,那么你也可以建立一个start-array)
- 然后在解码时,使用多个线程一次解析多个索引点并将它们连接到目标列表或数组(imo 数组必须更快,因为你有总数的字段)
如果没有:
- 将遇到的每个字段开始推入队列(带有字段索引)并直接跳转到下一个字段
- 由其他线程从队列中异步弹出元素,并根据它们的索引将它们放入列表中(如果知道总长度,数组可能会更好)
因为当您在同一个循环中同时进行提取和解析时,提取吞吐量会下降。因此,您应该将工作卸载到其他线程,也许一次使用 N 个字段以容忍 multi-threading 同步延迟。
如果 single-thread 提取比 multi-thread 解析太慢,那么您可以尝试矢量化提取。一次启动 128 个字符采样器,检查它们是否找到前缀代码并在它们之间进行归约以找到其中的第一个前缀(如果找到多个)。