【问题标题】:Text written to Console after reading from .txt file using streamreader only partially appearing使用 streamreader 从 .txt 文件读取后写入控制台的文本仅部分出现
【发布时间】:2014-04-15 20:57:30
【问题描述】:

我正在尝试按他们居住的城镇搜索存储在文本文件中的客户帐户。三个客户帐户都属于不同的城镇。我认为该程序找到了正确的客户,因为它确实返回要写入屏幕的数据,但不是全部。这些图像更好地解释了它。试图嵌入它们但没有积分

文本文件内容:

搜索居住在利物浦的客户时(虽然图片没有显示,但光标开始在 DOB 下方闪烁 5 行)

正在寻找贝尔法斯特客户。请注意,它获取了 coreect DOB 但错误的客户编号和姓氏。(我会把链接放在评论中它不会让我发布超过 2 个链接)

这是方法的代码::

static void FindTown(CustomerStruct[] CustomerDeats)
    {
        string City;
        bool CityMatch = false;
        Console.Clear();

    begin:
        try
        {
            Console.WriteLine("Please enter the customers Town ");
            City = Console.ReadLine();                
        }
        catch
        {
            Console.WriteLine("Failed. Please try again.");
            goto begin;
        }

        var pathToTown = @"..\..\..\Files\Customer.txt";

        using (StreamReader sr = new StreamReader(pathToTown))

            while (!CityMatch)
            {

                {
                    RecCount = 0;

                    CustomerDeats[RecCount].Town = sr.ReadLine();

                    if (City == CustomerDeats[RecCount].Town)
                    {

                        Console.WriteLine("\n\n");

                        CityMatch = true;



                        CustomerDeats[RecCount].CustomerNo = sr.ReadLine();
                        Console.WriteLine(CustomerDeats[RecCount].CustomerNo);

                        CustomerDeats[RecCount].Surname = sr.ReadLine();
                        Console.WriteLine(CustomerDeats[RecCount].Surname);

                        CustomerDeats[RecCount].Forename = sr.ReadLine();
                        Console.WriteLine(CustomerDeats[RecCount].Forename);

                        CustomerDeats[RecCount].Street = sr.ReadLine();
                        Console.WriteLine(CustomerDeats[RecCount].Street);

                        CustomerDeats[RecCount].Town = sr.ReadLine();
                        Console.WriteLine(CustomerDeats[RecCount].Town);

                        CustomerDeats[RecCount].DOB = sr.ReadLine();
                        Console.WriteLine(CustomerDeats[RecCount].DOB);

                        Console.ReadKey();


                    }

                    RecCount++;

                }

            }
    }

【问题讨论】:

标签: c# streamreader


【解决方案1】:

如果我是你,我要做的第一件事就是更好地理解StreamReader 的工作方式。每次您拨打ReadLine() 时,您在文件中的位置都会前进另一行。我会重新考虑你的算法。也许是这样的:

  1. 读取文件中的所有行并在空行处拆分。
  2. 将非空行存储在某种包含所有信息的对象中。
  3. 搜索您的对象以找到您要查找的内容(例如:城镇 == 利物浦)。

如果您不了解读取文件的工作原理,那么在读取文件时尝试这样做会变得很困难。

只是一个想法。 :-)

【讨论】:

    【解决方案2】:

    您正在搜索包含城镇的行,找到后立即阅读接下来的五行。但问题是您的信息在城镇之前,您需要阅读城镇之前的四行,以及城镇(日期)之后的行。

    这是一种执行此操作的方法,但不是那么优雅。您可以使用临时列表来存储已读取的行,然后当您找到要查找的记录时,会显示列表中的先前项目(行),如下所示:

    using (StreamReader sr = new StreamReader(pathToTown))
    {
        var tempLines = new List<string>();
        while (!CityMatch && !sr.EndOfStream)
        {
    
            string line = sr.ReadLine();
    
            if (City == line)
            {
                Console.WriteLine("\n\n");
                CityMatch = true;
                int count = tempLines.Count;
                Console.WriteLine("Customer No: {0}", tempLines[count-4]);
                Console.WriteLine("Customer Surname: {0}", tempLines[count - 3]);
                Console.WriteLine("Customer Forename: {0}", tempLines[count - 2]);
                Console.WriteLine("Customer Street: {0}", tempLines[count - 1]);
                Console.WriteLine("Customer Town: {0}", line);
                Console.WriteLine("Customer Day Of Birth: {0}", sr.ReadLine());
                Console.ReadKey();
    
            }else tempLines.Add(line);
    
        }
    }
    

    您可以将此逻辑应用于您的代码。顺便说一句,我还在您的 while 循环中添加了另一个条件,以使您免于无限循环。 (!sr.EndOfStream) 如果您到达流的末尾,它将中断循环,如果您输入文件中不存在的城镇,那么您的循环将是 infinite 因为CityMatch 永远不会会变的。

    只是为了多样性,这里是使用LINQ的另一种方式:

     var town = Console.ReadLine();
     var record = File.ReadLines("filepath")
                  .Where(x => x != string.Empty)
                  .Select((line, idx) => new {line, idx})
                  .GroupBy(x => x.idx/6)
                  .FirstOrDefault(x => x.Any(e => e.line.Contains(town)));
    
    if (record != null)
    {
         var values = record.Select(x => x.line).ToArray();
         Console.WriteLine("Customer No: {0}", values[0]);
         Console.WriteLine("Customer Surname: {0}", values[1]);
         Console.WriteLine("Customer Forename: {0}", values[2]);
         Console.WriteLine("Customer Street: {0}", values[3]);
         Console.WriteLine("Customer Town: {0}", values[4]);
         Console.WriteLine("Customer Day Of Birth: {0}", values[5]);
    }
    

    【讨论】:

    • 我明白你的意思了,我如何告诉程序在找到城市后返回四行?
    • 非常感谢,非常感谢!
    • 辛苦了,谢谢!
    【解决方案3】:

    你的问题出在这里:

    CustomerDeats[RecCount].Town = sr.ReadLine();
    
    if (City == CustomerDeats[RecCount].Town)
    

    只有当您读入正确的城市名称后,if 才会为真。根据您的文件,这意味着您只会读取文件的最后一行,然后将其写入控制台。

    顺便说一句,提供文件中未找到的名称将导致无限循环。

    【讨论】:

      【解决方案4】:

      当阅读器到达一个城市时,您开始阅读客户的数据,但只有 1 条记录的字段在城市之后。考虑先将所有数据读入内存。例如 - 进入数组。像这样的:

      string s = File.ReadAllText(pathToTown).Trim();
      string[] customersUnparsed = s.Split(new[] { Environment.NewLine + Environment.NewLine },
          StringSplitOptions.RemoveEmptyEntries);
      string[][] customers = Array.ConvertAll(customersUnparsed,
          c => c.Split(new[] { Environment.NewLine }, StringSplitOptions.None));
      

      使用示例:

      string[] customer = Array.Find(customers, c => c[4] == "Liverpool");
      

      这段代码不够完美。我意识到为客户创建class 或struct 会更好,但我相信它可能会为您指明正确的方向。

      【讨论】:

      • ReadAllText 的意义何在?您可以使用File.ReadLines 并过滤空行
      • 我知道,但是使用双 Environment.NewLine 拆分更容易。
      【解决方案5】:

      首先,如果用户输入的单词不在文件中,您的代码将进入无限循环。在您的示例中,它是利物浦您也需要检查 EndOfStream。 http://msdn.microsoft.com/en-us/library/vstudio/system.io.streamreader.endofstream

      ReadLine 方法读取一行并推进指针。 http://msdn.microsoft.com/en-us/library/vstudio/system.io.streamreader.readline

      在您的示例代码中,这里是被读入属性 Town 直到遇到利物浦的内容。这是进入城镇的每条阅读线。

      城镇是“1000”, 小镇是“拉姆齐”, 小镇是“亚伦”, 小镇是“10 Mews Park”, 小镇是“加的夫”, 镇是“03/07/1989”, 镇是“1001”, 镇是“科尔”, 小镇是“乔”, 小镇是“10 The Meadows”, 小镇是“贝尔法斯特”, 镇是“04/06/1969”, 镇是“1002”, 小镇是“Whilshere”, 镇是“杰克”, 镇是“9主教溪”, 小镇是“利物浦”

      请记住,每次 ReadLine 时文件指针都会前进。

      从输出屏幕截图中可以看出,仅打印了最终记录的 DOB。这是因为,如上所示,文件中的所有数据都已从流中消耗。

      RecCount 的最终值也将始终为 1。在循环的每次迭代开始时将其重置为 0。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-16
        • 1970-01-01
        • 2020-06-10
        • 2012-07-29
        • 2012-02-01
        相关资源
        最近更新 更多