【问题标题】:Dynamically create new List<strings> and add n number of lines - C#动态创建新的 List<strings> 并添加 n 行 - C#
【发布时间】:2018-08-24 05:01:20
【问题描述】:

我正在尝试使用 StreamReader 读取文件。该文件包含以下数据(还有 40,000 多行!):

    Tyndall Centre grim file created on 22.01.2004 at 17:57 by Dr. Tim Mitchell
.pre = precipitation (mm)
CRU TS 2.1
[Long=-180.00, 180.00] [Lati= -90.00,  90.00] [Grid X,Y= 720, 360]
[Boxes=   67420] [Years=1991-2000] [Multi=    0.1000] [Missing=-999]
Grid-ref=   1, 148
 3020 2820 3040 2880 1740 1360  980  990 1410 1770 2580 2630
 3020 2820 3040 2880 1740 1360  980  990 1410 1770 2580 2630
 3020 2820 3040 2880 1740 1360  980  990 1410 1770 2580 2630
 3020 2820 3040 2880 1740 1360  980  990 1410 1770 2580 2630
 3020 2820 3040 2880 1740 1360  980  990 1410 1770 2580 2630
 3020 2820 3040 2880 1740 1360  980  990 1410 1770 2580 2630
 3020 2820 3040 2880 1740 1360  980  990 1410 1770 2580 2630
 3020 2820 3040 2880 1740 1360  980  990 1410 1770 2580 2630
 3020 2820 3040 2880 1740 1360  980  990 1410 1770 2580 2630
 3020 2820 3040 2880 1740 1360  980  990 1410 1770 2580 2630
Grid-ref=   1, 311
  490  290  280  230  200  250  440  530  460  420  530  450
  490  290  280  230  200  250  440  530  460  420  530  450
  490  290  280  230  200  250  440  530  460  420  530  450
  490  290  280  230  200  250  440  530  460  420  530  450
  490  290  280  230  200  250  440  530  460  420  530  450
  490  290  280  230  200  250  440  530  460  420  530  450
  490  290  280  230  200  250  440  530  460  420  530  450
  490  290  280  230  200  250  440  530  460  420  530  450
  490  290  280  230  200  250  440  530  460  420  530  450
  490  290  280  230  200  250  440  530  460  420  530  450
Grid-ref=   1, 312
  460  280  260  220  190  240  430  520  450  400  520  410
  460  280  260  220  190  240  430  520  450  400  520  410
  460  280  260  220  190  240  430  520  450  400  520  410
  460  280  260  220  190  240  430  520  450  400  520  410
  460  280  260  220  190  240  430  520  450  400  520  410
  460  280  260  220  190  240  430  520  450  400  520  410
  460  280  260  220  190  240  430  520  450  400  520  410
  460  280  260  220  190  240  430  520  450  400  520  410
  460  280  260  220  190  240  430  520  450  400  520  410
  460  280  260  220  190  240  430  520  450  400  520  410

我已经设法阅读了前 5 行并将这些行添加到列表中。现在,我想阅读包含以下内容的行:

网格参考 = 1, 148

和下面的 10 行,所以它在之前读完:

网格参考 = 1, 311

然后我想将这些行添加到一个新列表中,但是我不想一遍又一遍地创建一个新列表。

到目前为止,它捕获了这两行:

网格参考 = 1, 148

3020 2820 3040 2880 1740 1360 980 990 1410 1770 2580 2630

这是我目前所拥有的:

    private void button1_Click(object sender, EventArgs e)
{

    var list = new List<string>();
    List<string> HeaderParse = new List<string>();

    List<string> GridRefList = new List<string>();


    var regex = new Regex(@"(Grid-ref)");

    using (var sr = new StreamReader("cru-ts-2-10.1991-2000-cutdown.pre"))
    {
        string line;
        while((line = sr.ReadLine()) != null)
        {
            list.Add(line);
        }

        for(int a = 0; a < list.Count; a++)
        {
            if (!regex.IsMatch(list[a]))
            {
                HeaderParse.Add(list[a]);
            }
            else
            {
                break;
            }
        }

        for(int b = 0; b < list.Count; b++)
        {
            if (regex.IsMatch(list[b]))
            {
                GridRefList.Add(list[b]);

                b++;

                if (!regex.IsMatch(list[b]))
                {
                    GridRefList.Add(list[b]);
                }
                break;
            }
        }

    }

    MessageBox.Show("This button has been clicked");
}

我需要有关如何告诉 StreamReader 在匹配后读取接下来的 10 行并在遇到包含“Grid-ref”的新行时创建一个新列表的帮助。

【问题讨论】:

  • 这是什么类型的文件?是否有一个已经存在的解析器可用,因此您不必重新发明它?
  • 您会一次处理一个标题行之间的这些组吗?
  • 另外,您将如何使用带数字的行?可能值得编写一个类来保存每个组中的数据
  • @Igor 这是一个 .pre 文件。
  • @MOMI StreamReader 很好,但是将整个文件读入List 只是为了处理List 一次一行只是浪费内存。读取并处理每一行并转储List 缓冲区。

标签: c# list streamreader


【解决方案1】:

这不是对您的具体问题的回答,而是您可以采取的可能的设计实施路线。不确定数据将如何使用,但您可以手动将此数据序列化为支持您想要执行的工作类型的自定义类:

public class PrecipitationFile
{
    string FileName { get; }
    public IList<PrecipitationGrid> Grids { get; }
    int BoxCount { get; }
    double Multi { get; }
    int Missing { get; }
    IList<string> Years { get; }

    public PrecipitationFile(string filePath)
    {
        // Read file, set properties, split by grid-ref chunks
        // Grids.Add(new PrecipitationGrid(this, chunk));
    }
}

public class PrecipitationGrid
{
    int Id { get; }
    int Ref { get; }
    PrecipitationFile Header { get; }
    string Source { get; }
    IList<int> GridNumbers { get; set; }

    public PrecipitationGrid(PrecipitationFile header, string source)
    {
        // set properties
    }
}

【讨论】:

    【解决方案2】:

    制作一个列表列表。每次遇到“Grid-ref”时,在深度 1 处创建一个新列表。在深度 2 处添加 10 行左右的数据。这样您的所有数据都包含在一个大列表中,但被整齐地分割。

    List<List<string>> data = new List<List<string>>();
    var list = new List<string>();
    var regex = new Regex(@"(Grid-ref)");
    
    using (var sr = new StreamReader("cru-ts-2-10.1991-2000-cutdown.pre"))
    {
        string line;
        while((line = sr.ReadLine()) != null)
        {
            list.Add(line);
        }
    
        for(int i = 0; i < list.Count; i++)
        {
            if (regex.IsMatch(list[i])) //line matches "Grid=ref"
            {
                List<string> data_block = new List<string>(); //data_block is for the 10 lines
                data.Add(data_block); //add data_block list to bigger 2D list
            }
            else //other data
            {
                data[data.Count].Add(list[i]); //put other data into the most recent list
            }
        }
    }
    

    您也不需要使用正则表达式,因为它是一项昂贵的操作。我建议用

    替换它
    if(list[i].Contains("Grid-ref"))
    

    【讨论】:

    • 这行不通,因为前 5 行。它将转到第一行的else 并导致NullReferenceException
    • 对,我没有看到文件的那部分,但这是一个简单的修复。读取“Grid-ref”后,将布尔值设置为 true。如果是这样,则添加到列表中。
    【解决方案3】:

    首先,不要试图同时进行文件读取和数据操作。首先读取文件并将其放入一个简单的字符串列表中,然后完成文件读取。然后,操作数据。我已经添加了 cmets,所以它应该是不言自明的。

    static void Main(string[] args)
    {
        var lines = ReadFile("input.txt");
    
        List<List<string>> data = new List<List<string>>();
        var firstHeader = false;
        foreach (var line in lines)
        {
            if (!firstHeader && line.StartsWith("Grid-ref="))
            {
                // Found the first header
                firstHeader = true;
                // Let's create a new list and add the header.
                var newList = new List<string> { line };
                data.Add(newList);
            }
            else if (firstHeader && !line.StartsWith("Grid-ref="))
            {
                // Now we're at the number lines to its corresponding list.
                data.Last<List<string>>().Add(line);
            }
            else if (firstHeader && line.StartsWith("Grid-ref="))
            {
                // Found the next header.
                // So we create next list and add the header.
                var newList = new List<string> { line };
                data.Add(newList);
            }
        }
    
        Console.ReadLine();
    }
    
    private static List<string> ReadFile(string file)
    {
        var list = new List<string>();
    
        using (var sr = new StreamReader(file))
        {
            while (!sr.EndOfStream)
            {
                list.Add(sr.ReadLine());
            }
        }
    
        return list;
    }
    

    这是data最后的样子。

    【讨论】:

      猜你喜欢
      • 2017-07-14
      • 1970-01-01
      • 2019-12-31
      • 2023-02-24
      • 2012-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多