【问题标题】:Parsing text file using C#使用 C# 解析文本文件
【发布时间】:2010-08-08 17:58:29
【问题描述】:

寻找一种很好的方法来解析这个文本文件,使用 C# 用黄色框突出显示的值。每个部分都由我忘记突出显示的 TERM # 来描述。试过这个:

string fileName = "ATMTerminalTotals.txt";
StreamReader sr = new StreamReader(fileName);
string[] delimiter = new string[] { " " };
while (!sr.EndOfStream)
{
     string[] lines = sr.ReadLine().Split(delimiter, StringSplitOptions.RemoveEmptyEntries);
     foreach (string line in lines)
     {
         Console.WriteLine(line);
     }
}
Console.ReadLine();

可以肯定地说我正在正确阅读行并删除“空白”。虽然,作为一个编程爱好者,不确定一种有效的方法来准确地“知道”我从这份报告中得到了我需要的值。有什么建议吗?

【问题讨论】:

  • 编写单元测试以证明您可以合理预期遇到的情况不会违反您的假设。 (并测试当你的假设也被违反时会发生什么,只是为了好玩。)
  • 不一定与解析逻辑相关,但您可能会发现 File.ReadAllLines(或 File.ReadLines,如果文件很大并且您使用的是 .NET 4.0)可能有助于摆脱所有 StreamReader混乱。

标签: c# regex text-parsing


【解决方案1】:

我已经用一个非常简单的程序对此进行了测试,以解析给定的文件, 基本上我已经创建了两个基本类,一个页面类包含终端报告类的集合(tran 类型行) 这些行甚至可以表示为交易和计费类

首先解析数据,设置所需参数,最后访问属性

只是把它尽可能简单,没有错误处理等......它只是让你了解 id 如何开始解决这些任务,希望它有所帮助

亚当

namespace TerminalTest
{
    class Program
    {
        public class TerminalReport
        {
            public string Word { get; set; }

            public int Denials { get; set; }

            public int Approvals { get; set; }

            public int Reversals { get; set; }

            public double Amount { get; set; }

            public int ON_US { get; set; }

            public int Alphalink { get; set; }

            public int Interchange { get; set; }

            public int Surcharged { get; set; }

            public static TerminalReport FromLine(string line)
            {
                TerminalReport report = new TerminalReport();
                report.Word = line.Substring(0, 11);
                line = line.Replace(report.Word, string.Empty).Trim();
                string[] split = line.Split(' ');
                int i = 0;
                // transaction summary
                report.Denials = int.Parse(split[i++]);
                report.Approvals = int.Parse(split[i++]);
                report.Reversals = int.Parse(split[i++]);
                report.Amount = double.Parse(split[i++]);
                // billing counts
                report.ON_US = int.Parse(split[i++]);
                report.Alphalink = int.Parse(split[i++]);
                report.Interchange = int.Parse(split[i++]);
                report.Surcharged = int.Parse(split[i++]);

                return report;
            }
        }

        public class TerminalPage
        {
            public int PageNumber { get; set; }

            public double TotalSurcharges { get; set; }

            public List<TerminalReport> Rows { get; set; }

            public TerminalPage(int num)
            {
                PageNumber = num;
                Rows = new List<TerminalReport>();
            }

            public int TotalDenials
            {
                get
                {
                    return rows.Sum(r => r.Denials);
                }
            }

            public int TotalApprovals
            {
                get
                {
                    return Rows.Sum(r => r.Approvals;
                }
            }

            public int TotalReversals
            {
                get
                {
                    return Rows.Sum(r => r.Reversals;
                }
            }

            public double TotalAmount
            {
                get
                {
                    return Rows.Sum(r => r.Amount);
                }
            }

            public int TotalON_US
            {
                get
                {
                    return Rows.Sum(r => r.ON_US);
                }
            }

            public int TotalAlphalink
            {
                get
                {
                     return Rows.Sum(r => r.Alphalink);
                }
            }

            public int TotalInterchange
            {
                get
                {
                     return Rows.Sum(r => r.Interchange);
                }
            }

            public int TotalSurcharged
            {
                get
                {
                     return Rows.Sum(r => r.Surcharged);
                }
            }
        }

        private static string CleanString(string text)
        {
            return Regex.Replace(text, @"\s+", " ").Replace(",", string.Empty).Trim();
        }

        private static List&lt;TerminalPage&gt; ParseData(string filename)
        {
            using (StreamReader sr = new StreamReader(File.OpenRead(filename)))
            {
                List<TerminalPage> pages = new List<TerminalPage>();

                int pageNumber = 1;
                TerminalPage page = null;
                bool parse = false;
                while (!sr.EndOfStream)
                {
                    string line = sr.ReadLine();
                    line = CleanString(line);
                    if (line.StartsWith("TRAN TYPE"))
                    {
                        // get rid of the ----- line
                        sr.ReadLine();

                        parse = true;
                        if (page != null)
                        {
                            pages.Add(page);
                        }
                        page = new TerminalPage(pageNumber++);
                    }
                    else if (line.StartsWith("="))
                    {
                        parse = false;
                    }
                    else if (line.StartsWith("TOTAL SURCHARGES:"))
                    {
                        line = line.Replace("TOTAL SURCHARGES:", string.Empty).Trim();
                        page.TotalSurcharges = double.Parse(line);
                    }
                    else if (parse)
                    {
                        TerminalReport r = TerminalReport.FromLine(line);
                        page.Rows.Add(r);
                    }
                }
                if (page != null)
                {
                    pages.Add(page);
                }

                return pages;
            }
        }

        static void Main(string[] args)
        {
            string filename = @"C:\bftransactionsp.txt";
            List<TerminalPage> pages = ParseData(filename);

            foreach (TerminalPage page in pages)
            {
                Console.WriteLine("TotalSurcharges: {0}", page.TotalSurcharges);
                foreach (TerminalReport r in page.Rows)
                        Console.WriteLine(r.Approvals);

            }
        }
    }
}

【讨论】:

  • 不错的代码 :) 我只是使用 C# 3.0 功能对其进行了略微改进以减小大小
【解决方案2】:

我不确定我是否会用空格分割它。文本文件看起来像是分割成列。您可能希望一次读取 10 个字符(或任何列的宽度)......我会将整个文件解析为字典,以便您获得类似

的条目
dict["WDL FRM CHK"]["# DENIALS"] = 236

然后您可以轻松地从那里检索您想要的值,并且如果您将来需要更多值,您已经得到了它们。


或者,您可以使用正则表达式。您可以使用正则表达式获取第一个值,例如

^WDL FRM CHK\s+(?<denials>[0-9,]+)\s+(?<approvals>[0-9,]+)$

使用

m.Groups["approvals"]

【讨论】:

    【解决方案3】:

    无论如何,我建议你用using 块包装你的StreamReader

    using (StreamReader sr = new StreamReader(fileName))
    {
        // do stuff
    }
    

    阅读更多MSDN

    【讨论】:

      【解决方案4】:

      鉴于它似乎具有标准的常规格式,我会使用正则表达式。您可以检查起始代码以确定您所在的行,然后解析出数字并忽略空格的表达式很可能比手动处理更容易。

      【讨论】:

        【解决方案5】:
        using System;
        using System.Text.RegularExpressions;
        
        namespace ConsoleApplication3
        {
          class Program
          {
            static void Main(string[] args)
            {
              Regex exp = new Regex(@"WDL FRM CHK(\s)+[1-9,]+(\s)+(?<approvals>[1-9,]+)(\s)+");
              string str = "WDL FRM CHK   236   1,854   45,465  123     3";
              Match match = exp.Match(str);
        
              if (match.Success)
              {
                Console.WriteLine("Approvals: " + match.Groups["approvals"].Value);
              }
        
              Console.ReadLine();
            }
          }
        }
        

        改编自以下文章以解析您的一个数字:

        【讨论】:

          猜你喜欢
          • 2013-12-10
          • 1970-01-01
          • 2010-10-25
          • 1970-01-01
          • 2015-01-07
          • 1970-01-01
          • 1970-01-01
          • 2013-11-28
          • 1970-01-01
          相关资源
          最近更新 更多