【问题标题】:TextFieldParser equivalent in .NET?.NET 中的 TextFieldParser 等效项?
【发布时间】:2013-12-25 16:51:28
【问题描述】:

是否存在与 VB6 中的 TextFieldParser 类等效的现代 .NET?性能比简单的String.Split()低很多

【问题讨论】:

  • 性能低很多是什么意思?您是否进行了基准测试?
  • 我不明白 ..TextFieldParser 是 .NET 库的一部分
  • @meda 是旧 VisualBasic 的一部分,所以如果我没记错的话,它是 .NET 的包装器,比如 Left、Right 和那些旧的 VB 方法
  • 一些 >100K 的人最近发表评论说,使用 String.Split 解析 CSV 是邪恶的/愚蠢的/糟糕的,但从未扩展任何替代方案。我怀疑TextFieldParser 是答案,因为每个人都知道它很慢,而且由于它在 VB 空间中,对于经验不足的人来说,它是那些高级别的东西之一(可以说)。
  • .Net 的 TextFieldParser 不是一些 VB6 东西的包装器。此外,它并不慢,因为它在Microsoft.VisualBasic 中(这很愚蠢)。它比简单的 String.Split 慢,因为它实际上解析 CSV 数据(并尊重引号和分隔引号)。每次正确解析 CSV 数据都会比String.Split 慢。如果你正在寻找一个强大的解析库,我推荐FileHelpers

标签: c# .net vb.net csv frameworks


【解决方案1】:

这是我的解决方案:

public class TextFieldParser
    {
        enum FieldType { FixedWidth, Delimited };

        public enum CompleteElements 
        {
            /// <summary>
            /// Returns as many elements as fileWidths input be
            /// </summary>
            AllElements, 
            /// <summary>
            /// Only returns elements who have not null values
            /// </summary>
            OnlyValues 
        };

        int[] m_fieldWidths;
        string m_line;
        List<string> m_results;
        int m_lineWidth;
        public CompleteElements m_CompleteElements;

        public TextFieldParser(string line)
        {
            m_line = line;
            m_lineWidth = m_line.Length;
            m_results = new List<string>();
            m_CompleteElements = CompleteElements.OnlyValues;
        }

        public void SetCompleteElements(CompleteElements value) 
        {
            m_CompleteElements = value;
        }

        public void SetFieldWidths(params int[] fileWidths)
        {
            m_fieldWidths = fileWidths;
        }

        public string[] ReadFields()
        {
            int pivot = 0;
            m_results = new List<string>();

            for (int x = 0; x < m_fieldWidths.Length; x++) 
            {
                if(pivot + m_fieldWidths[x] <= m_lineWidth)
                {
                    m_results.Add(m_line.Substring(pivot, m_fieldWidths[x]));                    
                }
                else
                {
                    if (m_CompleteElements == CompleteElements.AllElements) 
                    {
                        m_results.Add(null);
                    }

                    break;
                }
                pivot += m_fieldWidths[x];
            }
            return m_results.ToArray();
        }
    }

一个简单的会话:

string line = "1234567890123456789012345678890";
TextFieldParser parser = new TextFieldParser(line);
parser.SetFieldWidths(1, 2, 3, 4, 5, 6, 7, 8);

string[] resultOnlyValues = parser.ReadFields();
/*
results:
resultOnlyValues[0] : "1"
resultOnlyValues[1] : "23"
resultOnlyValues[2] : "456"
resultOnlyValues[3] : "7890"
resultOnlyValues[4] : "12345"
resultOnlyValues[5] : "678901"
resultOnlyValues[6] : "2345678"
*/
parser.SetCompleteElements(TextFieldParser.CompleteElements.AllElements);
string[] resultAllElement = parser.ReadFields();
/*
results:
resultAllElement[0] : "1"
resultAllElement[1] : "23"
resultAllElement[2] : "456"
resultAllElement[3] : "7890"
resultAllElement[4] : "12345"
resultAllElement[5] : "678901"
resultAllElement[6] : "2345678"
resultAllElement[7] : null
*/

【讨论】:

    【解决方案2】:

    我已经将性能与该代码进行了比较:https://gist.github.com/Ruszrok/7861319

    我使用了一个输入文件,其中包含大约 1 000 000 条用空格分隔的记录。我尝试了五个实验。

    • String.Split 平均时间:291 毫秒
    • Microsoft.VisualBasic.FileIO.TextFieldParser 平均时间:15843 毫秒

    您可以使用Microsoft.VisualBasic.FileIO.TextFieldParser 类。参考Microsoft.VisualBasic。要点示例。

    【讨论】:

    • 但是 string.split 不会考虑整个 CSV 规范 - 例如嵌入在字段中的逗号和引号不会与 string.split 方法混淆 - 因此您可以使用拆分方法 -但只有你能确定你的数据会是什么样子
    • 您的string.Split 测试代码只读取一行并以空格分隔,而TextFieldParser 必须读取并解析整个文件。当然,这需要更多毫秒。但整个比较都是无稽之谈。为工作使用正确的工具。如果您有真正的 csv 数据(例如,如果字段用引号括起来),TextFieldParser 比简单的 String.Split 更强大。
    猜你喜欢
    • 1970-01-01
    • 2010-09-20
    • 2010-10-19
    • 2011-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    • 2011-05-18
    相关资源
    最近更新 更多