【问题标题】:C# reading multiple lines into a single variableC#将多行读入单个变量
【发布时间】:2017-03-05 20:54:20
【问题描述】:

我已经查看但未能找到可以解决我的问题的教程。也许我没有正确地用词我的搜索。无论如何,我在这里。

我接管了一家杂工公司,他有大约 150 名客户。他购买了一个程序,为他的客户制作唱片。我有记录,但他不会把这个程序卖给我,因为它是商业的,而且他害怕因为出售类似的东西而入狱......无论如何......它们都写在一个文本文件中。格式似乎是:

string name
string last_job_description
int    job_codes
string job_address
string comments

文本文件如下所示

*Henderson*
*Cleaned gutters, fed the lawn, added mulch to the front flower beds,
 cut the back yard, edged the side walk, pressure washed the driveway*
*04 34 32 1 18 99 32 22 43 72 11 18*
*123 Anywhere ave*
*Ms.always pays cash no tip. Mr. gives you a check but always tips*

好吧..我的问题是在 C# 中我想编写一个程序来编辑这些记录,添加新客户并删除一些我可能会丢失、移动或死亡的...但是第二个条目有时会超过两行3 和 4 行。它们都以 * 开头和结尾。那么,如何读取 2 到 4 行并将它们放入 last_job_description 字符串变量中?我可以写课程,我可以读行,我可以去掉星号。在将多行读入单个变量时,我什么也找不到。

【问题讨论】:

  • 您必须分别阅读每一行,然后根据第一行的样子(如果它有足够的星号),您必须决定是阅读下一行并追加还是停止。 .NET 中的文本阅读器没有读取多行的方法,除了 ReadToEnd 或类似的,所以你只需要自己阅读这些行,一次一个。
  • 或者你可以看看 nuget 上是否有一个 CSV 导入库可以处理数据中的换行符。
  • 使用 File.ReadAllLines
  • 您可以使用 File.ReadAllText 将整个文件读入string msdn.microsoft.com/en-us/library/ms143368(v=vs.110).aspx
  • '*'出现在文本中时会发生什么,它是如何转义的?

标签: c# readline


【解决方案1】:

让我们做对吧!

首先定义客户模型:

public class Customer
{
    public string Name { get; set; }
    public string LastJobDescription { get; set; }
    public List<int> JobCodes { get; set; }
    public string JobAddress { get; set; }
    public string Comments { get; set; }
}

那么,我们需要一个客户集合:

var customers = new List<Customer>();

用文件中的数据填充集合:

string text = File.ReadAllText("customers.txt");
string pattern = @"(?<= ^ \*) .+? (?= \* \r? $)";

var options = RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled
    | RegexOptions.Singleline | RegexOptions.Multiline;
var matches = Regex.Matches(text, pattern, options);

for (int i = 0; i < matches.Count; i += 5)
{
    var customer = new Customer
    {
        Name = matches[i].Value,
        LastJobDescription = matches[i + 1].Value,
        JobCodes = matches[i + 2].Value.Split().Select(s => int.Parse(s)).ToList(),
        JobAddress = matches[i + 3].Value,
        Comments = matches[i + 4].Value
    };
    customers.Add(customer);
}

我正在使用一个正则表达式,它允许将* 字符放在行的中间。

现在我们可以轻松地使用这个集合了。


使用示例。

删除第一个客户:

customers.RemoveAt(0);

给最新的客户端添加评论:

customers.Last().Comments += " Very generous.";

根据 Henderson 的名称查找客户的第一条记录,并添加所执行工作的代码:

customers.Find(c => c.Name == "Henderson").JobCodes.Add(42);

添加新客户:

var customer = new Customer
{
    Name = "Chuck Norris",
    LastJobDescription= "Saved the world.",
    JobCodes = new List<int>() { 1 },
    JobAddress = "UN",
    Comments = "Nice guy!"
};
customers.Add(customer);

等等。


要将数据保存到文件,请使用以下命令:

var sb = new StringBuilder();
foreach (var customer in customers)
{
    sb.Append('*').Append(customer.Name).Append('*').AppendLine();
    sb.Append('*').Append(customer.LastJobDescription).Append('*').AppendLine();
    sb.Append('*').Append(string.Join(" ", customer.JobCodes)).Append('*').AppendLine();
    sb.Append('*').Append(customer.JobAddress).Append('*').AppendLine();
    sb.Append('*').Append(customer.Comments).Append('*').AppendLine();
}
File.WriteAllText("customers.txt", sb.ToString());

您可能需要一个图形用户界面。如果是这样,我建议您在指定使用什么的地方提出一个新问题:WinForms、WPF、Web 应用程序或其他。

【讨论】:

  • 你们应该写一篇关于这个的教程。我真的找不到很多。 Microsoft Visual C# 2013 一步一步是一匹马窒息 780 多页,甚至没有提到修剪/拆分/或任何这些东西。对此非常有必要。也许做一个YouTube视频或其他东西。我喜欢你所有的答案,我没有足够的代表点来喜欢他们,否则我会喜欢的。再次感谢大家。
【解决方案2】:

如果您想将文件中的所有行读入单个变量,那么您需要这样做

var txt = File.ReadAllText(.. your file location here ..);

或者你可以这样做

var lines = File.ReadAllLines(.. your file location here); 然后您可以遍历每一行并按原样删除 leave 的空白。

但根据你的问题,第一行是你真正想要的

【讨论】:

    【解决方案3】:

    当您应该阅读last_job_description 时阅读第二行。如果它以 * 开头,则表示该行是job_codes,否则将其附加到 pervous read 行。对每一行执行此操作,直到找到 job_codes

    using (var fileReader = new StreamReader("someFile"))
            {
                // read some pervous data here
    
                var last_job_description = fileReader.ReadLine();
                var nextLine = fileReader.ReadLine();
                while (nextLine.StartsWith("*") == false)
                {
                    last_job_description += nextLine;
                    nextLine = fileReader.ReadLine();
                }
                //you have job_codes in nextline, so parse it now and read next data
            }
    

    或者您甚至可以使用每组数据开始和结束的事实!!!使用*,因此您可以创建读取每个“集合”并将其作为单行字符串返回的函数,无论它实际上是多少行。假设您传递给此函数的 reader 变量与上面代码中的 StreamReader 相同

    function string readSingleValue(StreamReader fileReader){
        var result = "";
        do
        {
            result += fileReader.ReadLine().Trim();
        } while (result.EndsWith("*") == false);
        return result;
    }
    

    【讨论】:

      【解决方案4】:

      我认为您的问题有点复杂。我想说的是它没有提到具体问题。它包含至少 3 个不同的编程方面,您需要了解或学习以实现您的目标。您必须采取的步骤如下所述。

      • 很遗憾,您需要将当前文件视为巨大的字符串类型。
      • 然后你就可以处理这个字符串并分离不同的部分了。
      • 下一步是定义一个简洁、可靠且健壮的 XML 文件,该文件可以保存您的数据。
      • 用您操纵的字符串填写您的xml
      • 如果您有 xml 文件,您可以简单地更新它。

      【讨论】:

        【解决方案5】:

        没有内置方法可以完全按照您的需要解析文件,因此您必须亲自动手。

        以下是针对您的特定情况的工作代码示例。我假设你希望你的 job_codes 在一个数组中,因为它们是由空格分隔的多个整数。

        每次遇到以“*”开头的行时,我们都会增加一个计数器,告诉我们使用您的下一个属性(姓名、上一个职位描述等)。

        每一行都附加到当前属性。

        显然,我们从每行的开头和结尾删除了星号。

        string name = String.Empty;
        string last_job_description = String.Empty;
        int[] job_codes = null;
        string job_address = String.Empty;
        string comments = String.Empty;
        
        int numberOfPropertiesRead = 0;
        var lines = File.ReadAllLines("C:/yourfile.txt");
        
        for (int i = 0; i < lines.Count(); i++)
        {
            var line = lines[i];
            bool newProp = line.StartsWith("*");
            bool endOfProp = line.EndsWith("*");
        
            if (newProp)
            {
                numberOfPropertiesRead++;
                line = line.Substring(1);
            }
        
            if (endOfProp)
                line = line.Substring(0, line.Length - 1);
        
            switch (numberOfPropertiesRead)
            {
                case 1: name += line; break;
                case 2: last_job_description += line; break;
                case 3:
                    job_codes = line.Split(' ').Select(el => Int32.Parse(el)).ToArray();
                    break;
                case 4: job_address += line; break;
                case 5: comments += line; break;
                default:
                    throw new ArgumentException("Wow, that's too many properties dude.");
            }
        }
        
        Console.WriteLine("name: " + name);
        Console.WriteLine("last_job_description: " + last_job_description);
        foreach (int job_code in job_codes)
            Console.Write(job_code + " ");
        Console.WriteLine();
        Console.WriteLine("job_address: " + job_address);
        Console.WriteLine("comments: " + comments);
        Console.ReadLine();
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-07-29
          • 1970-01-01
          • 1970-01-01
          • 2016-09-14
          • 2013-02-15
          • 2013-09-18
          • 1970-01-01
          相关资源
          最近更新 更多