2016-03-01 75 views
1

我有一个读取文本文件的程序,我希望它在文本文件中的某个标题后收集数据,在这种情况下为[HRData]。一旦流媒体阅读器达到[HRData]我希望它读取每行后,并将每行存储在列表中,但允许我访问单独的数字。读取文本文件中特定字符串后的行,然后将数据存储在列表中

文本文件就像这样:

[HRZones] 
190 
175 
162 
152 
143 
133 
0 
0 
0 
0 
0 

[SwapTimes] 

[Trip] 
250 
0 
3978 
309 
313 
229 
504 
651 
//n header 
[HRData] 
91 154 70 309 83 6451 
91 154 70 309 83 6451 
92 160 75 309 87 5687 
94 173 80 309 87 5687 
96 187 87 309 95 4662 
100 190 93 309 123 4407 
101 192 97 309 141 4915 
103 191 98 309 145 5429 

所以参照文本文件,我想它来存储后[HRDATA]第一行,让我访问的每个变量,例如91[0]

我有代码已经存储到一个列表,如果单词匹配的正则表达式,但我不知道如何编码它读取像[HRData]之类的特定字符串。

if (squareBrackets.Match(line).Success) { 
titles.Add(line); 
if (textAfterTitles.Match(line).Success) { 
    textaftertitles.Add(line); 

} 
} 

这是迄今为止我尝试:

if (line.Contains("[HRData]")) { 
inttimes = true; 
MessageBox.Show("HRDATA Found"); 
if (inttimes == true) { 
    while (null != (line = streamReader.ReadLine())) { 
    //ADD LINE AND BREAK UP INTO PARTS S 
    } 
} 
} 
+0

可以读取HRDATA后线,分成每行的数据。当你看到什么让你停下来时停下来。 – sln

+0

是啊多数民众赞成在即时尝试实现,但多数民众赞成为什么我问这个问题,我不知道如何告诉我的代码阅读AFTER [HRData] –

+0

因为我目前的if语句if(line.Contains(“[HRData]”) ))只读取包含它的行,而我希望它在读取之后读取。 –

回答

2

意味着你的当前代码尝试的作品,我没有通过验证了......

你可以只需执行以下操作:

List<int> elements = new List<int>(); 
while (null != (line = streamReader.ReadLine())) 
{ 
    if(line.Contains("[")) 
    { 
     //Prevent reading in the next section 
     break; 
    } 
    string[] split = line.Split(Convert.ToChar(" ")); 
    //Each element in split will be each number on each line. 
    for(int i=0;i<split.Length;i++) 
    { 
     elements.Add(Convert.ToInt32(split[i])); 
    } 

} 

或者,如果您需要2维列表,以便您可以重新按行显示数字,可以使用嵌套列表。对于外部循环的每次运行,创建一个新列表并将其添加到元素(元素将是List<List<int>>)。

编辑

只是注意,小心使用Convert.ToInt32()函数。它应该真的在try catch语句中,以防一些读入的文本不是数字。

编辑

行..使例程更稳健(每低于我的意见):

首先确保例程不超越你的号码块。我不知道什么是超越你所列出的块,这样就会给你,但它应该采取以下形式:

If(line.Contains("[") || line.Contains("]") || etc etc etc) 
{ 
    break; 
} 

接下来的事情是预格式化您的拆分值。在for语句中:

for(int i=0;i<split.Length;i++) 
{ 
    string val = split[i].Trim(); //Get rid of white space 
    val = val.Replace("\r\n",""); //Use one of these to trim every character. 
    val = val.Replace("\n",""); 
    try 
    { 
     elements.Add(Convert.ToInt32()); 
    } 
    catch (Exception ex) 
    { 
     string err = ex.Message; 
     //You might try formatting the split value even more here and retry convert 
    } 

} 

要访问单个数字(假设您使用单维列表),有几种方法可以执行此操作。如果你想通过索引值来访问:

elements.ElementAt(index) 
如果您想通过值列表进行迭代

foreach(int val in elements) 
{ 
} 

如果您需要确切地知道哪行的价值是从哪里来的,我建议2d列表。这将实现如下(我复制从原来的代码片段我的代码,所以假定所有的错误检查的加入!)

List<List<int>> elements = new List<List<int>>(); 
while (null != (line = streamReader.ReadLine())) 
{ 
    if(line.Contains("[")) 
    { 
     //Prevent reading in the next section 
     break; 
    } 
    List<int> newLine = new List<int>(); 
    string[] split = line.Split(Convert.ToChar(" ")); 
    //Each element in split will be each number on each line. 
    for(int i=0;i<split.Length;i++) 
    { 
     newLine.Add(Convert.ToInt32(split[i])); 
    } 
    elements.Add(newLine); 
} 

我们访问由线的每个元素:

foreach(var line in elements) 
{ 
    //line is a List<int> 
    int value = line.ElementAt(index); //grab element at index for the given line. 
} 

另外,如果你需要直接行索引和列索引引用

int value = elements.ElementAt(lineIndex).ElementAt(columnIndex); 

注意所有这些直接的指标参考。你可以很容易地得到索引超出界限的问题。

另外一件事情..你应该在你的Convert.ToInt语句上放一个断点,并找出它打破的字符串。如果您可以假设数据输入是一致的,那么准确地找到打破转换的字符串将帮助您创建一个处理正在过滤的特定字符的例程。我会猜测,当它尝试将最后一个拆分值转换为整数,并且我们没有删除行尾。

+0

甜蜜的谢谢。它似乎运行良好。那我怎么能拨打存储的号码呢?例如,如果我想获得第一个数字? –

+0

另外,我得到错误输入字符串的格式不正确。在线elements.Add(Convert.ToInt32(split [i])); –

+0

拆分的元素之一是非数字,导致您的错误。我可能会打破'break'语句来确保它不会开始读取非数字的行。然后,将该转换放入try-catch中,以在该值为非数值的情况下捕获错误。我将编辑我的答案以提供更多信息。 –

3

可以调用一个LINQ友好的方法File.ReadLines,那么你可以使用LINQ来获取一部分,你想:

List<string> numbers = File.ReadLines("data.txt") 
          .SkipWhile(line => line != "[HRData]") 
          .Skip(1) 
          .SelectMany(line => line.Split()) 
          .ToList(); 

Console.WriteLine(numbers[0]); // 91 

编辑 - 这会给你所有的数字在一个List<string>,如果你想保持行顺序,使用Select而不是SelectMany

List<List<string>> listsOfNums = File.ReadLines("data.txt") 
            .SkipWhile(line => line != "[HRData]") 
            .Skip(1) 
            .Select(line => line.Split().ToList()) 
            .ToList(); 

请注意,这需要额外的指标得到一个数字:

Console.WriteLine(listsOfNums[0][0]); // 91 
+0

这看起来非常好,很简单,我将如何访问154,那会是[1]?那么下一行呢?谢谢。 –

2

你可以使用一个变量来跟踪当前节:

var list = new List<int[]>(); 
using (StreamReader streamReader = ...) 
{ 
    string line; 
    string sectionName = null; 
    while (null != (line = streamReader.ReadLine())) 
    { 
     var sectionMatch = Regex.Match(line, @"\s*\[\s*(?<NAME>[^\]]+)\s*\]\s*"); 
     if (sectionMatch.Success) 
     { 
      sectionName = sectionMatch.Groups["NAME"].Value; 
     } 
     else if (sectionName == "HRData") 
     { 
      // You can process lines inside the `HRData` section here. 

      // Getting the numbers in the line, and adding to the list, one array for each line. 
      var nums = Regex.Matches(line, @"\d+") 
       .Cast<Match>() 
       .Select(m => m.Value) 
       .Select(int.Parse) 
       .ToArray(); 

      list.Add(nums); 
     } 
    } 
} 
相关问题