0

我正在阅读一个大文件 X12 并解析其中的信息。我有两个似乎无法解决的瓶颈功能。read_line() 和 get_element() 有什么办法可以让这两个函数更快?get_element 函数的主要瓶颈似乎是 Substring 方法。

    public String get_element(int element_number) {
        int count = 0;
        int start_index = 0;
        int end_index = 0;
        int current_index = 0;

        while (count < element_number && current_index != -1) {
            current_index = line_text.IndexOf(x12_reader.element_delimiter, start_index);
            start_index = current_index + 1;
            count++;
        }

        if (current_index != -1) {
            end_index = line_text.IndexOf(x12_reader.element_delimiter, start_index);
            if (end_index == -1) end_index = line_text.Length;
            return line_text.Substring(start_index, end_index - start_index);
        } else {
            return "";
        }
    }

    private String read_line() {
        string_builder.Clear();
        int n;
        while ((n = stream_reader.Read()) != -1) {
            if (n == line_terminator) return string_builder.ToString();
            string_builder.Append((char)n);
        }
        return string_builder.ToString();
    }

我正在读取 x12 数据。这是它的外观示例。http://examples.x12.org/005010X221/dollars-and-data-sent-together/

4

3 回答 3

4

由于您的分析器告诉您这get_element是一个瓶颈,并且该方法本身的编码效率很高,因此您需要尽量减少调用此方法的次数。

在循环中重复调用get_element会强制它重复执行相同的解析工作:

for (int i = 0 ; i != n ; i++) {
    var element = get_element(i);
    ... // Do something with the element
}

您应该能够通过重写get_elementGetElements将所有元素作为集合返回,然后在循环中从同一集合中获取单个元素来解决此问题:

var allElements = GetElements();
for (int i = 0 ; i != n ; i++) {
    var element = allElements[i];
    ... // Do something with the element
}

在大多数情况下,我只需要一两个元素

在这种情况下,您可以创建一个方法来一次检索所有必需的索引 - 例如,通过传递BitArray必需的索引。

于 2016-08-30T14:26:02.650 回答
1

好的,第二次尝试。由于性能原因而丢弃String.Split,这样的事情应该比您的实现快得多:

//DISCLAIMER; typed in my cell phone, not tested. Sure it has bugs but you should get the idea.
public string get_element(int index)
{
     var buffer = new StringBuilder();
     var counter = -1;

     using (var enumerator = text_line.GetEnumerator())
     {
         while (enumerator.MoveNext())
         {
             if (enumerator.Current == x12_reader.element_delimiter)
             {
                 counter++;
             }
             else if (counter == index)
             {
                 buffer.Append(enumerator.Current);
             }
             else if (counter > index)
                 break;
        }
     }

     return buffer.ToString();
}
于 2016-08-30T14:36:29.537 回答
0

我不确定您到底在做什么,但是如果我正确理解了您的代码,那么元素是否会更简单如下?

public string get_Element(int index)
{
    var elements = line_text.Split(new[] { x12_reader.element_delimiter });

    if (index > elements.Length)
        return "";

    return elements[index];
}   
于 2016-08-30T14:26:54.417 回答