首页 > 解决方案 > 如何在不使用全局变量的情况下将文本文件读取到本地列表并定期返回以访问它?

问题描述

如果我声明这样的表(并从文本文件中填充它),我如何在声明局部变量的块之外访问名为 data 的变量。我想我必须将变量公开,但不知道如何公开表,也不知道在公开时如何访问它。

    var data = File.ReadAllLines(path)
      .Select(line => line.Split(','))
      .Select((cols, index) => new {
    Id=index,
    HardDriveDateTime = DateTime.Parse(cols[0]),
    CurrentOpen = decimal.Parse(cols[1]),
    CurrentHigh = decimal.Parse(cols[2]),
    CurrentLow = decimal.Parse(cols[3]),
    CurrentClose = decimal.Parse(cols[4]),
    Direction = cols[5],
    Pressure  = int.Parse(cols[6])
    }); 

标签: c#

解决方案


(这不是一个答案,但对于评论来说太长了)

在您的代码中,有一个以以下开头的部分:

if(firstpass == true)

在该块中,您正在读取保存的文本文件并将结果放入名为“hardDriveDateTime,currentOpen ...”的变量中。(如果我的代码正确,你想在最后一行这样做吗?)

作为一个老 Cobol 程序员,您可能会将这些行视为一个表格,其中这些变量可能是列名。然后该块可以重写为:

var data = File.ReadAllLines(path)
  .Select(line => line.Split(','))
  .Select((cols, index) => new {
    Id=index,
    HardDriveDateTime = DateTime.Parse(cols[0]),
    CurrentOpen = decimal.Parse(cols[1]),
    CurrentHigh = decimal.Parse(cols[2]),
    CurrentLow = decimal.Parse(cols[3]),
    CurrentClose = decimal.Parse(cols[4]),
    Direction = cols[5],
    Pressure  = int.Parse(cols[6])
});

对于上面给出的示例数据,如下所示:

Id|HardDriveDateTime   |CurrentOpen|CurrentHigh|CurrentLow|CurrentClose|Direction|Pressure
0 |7/20/2018 2:55:57 PM| 2804.5    | 2804.5    | 2804.5   | 2804.5     |   B     |  2210
1 |7/20/2018 3:07:57 PM| 2804.75   | 2804.75   | 2804.75  | 2804.75    |   S     |  125
2 |7/20/2018 3:11:06 PM| 2803.5    | 2803.5    | 2803.5   | 2803.5     |   B     |  255
3 |7/20/2018 3:14:42 PM| 2804      | 2804      | 2804     | 2804       |   S     |  -202
4 |7/20/2018 3:17:50 PM| 2802.75   | 2802.75   | 2802.75  | 2802.75    |   B     |  411
5 |7/20/2018 3:20:15 PM| 2803.75   | 2803.75   | 2803.75  | 2803.75    |   S     |  -1126

恕我直言,处理这样的表(IEnumerable)要容易得多。

高温高压

编辑:变量的范围是它们封闭的 {}。为了克服这个问题,创建全局变量(就像您所做的那样)很诱人,但是它们确实使事情变得更糟。相反,您可以在需要的地方传递这些变量。例如,在这种情况下,可能有一个 ReadTheFile("with a given path") 方法,并将该表作为类型化的 IEnumerable 返回。在我给出的代码中,IEnumerable 的行是匿名的,并且仅在周围的 {} 内局部有效。相反,我们可以创建一个与该表结构匹配的类并可以传递它。您的代码中有 XYValues 类。就像我们创建另一个一样(在一个单独的文件中,然后在一个大项目中处理它更容易)。

// MyData.cs
namespace yourNameSpaceName
{
    public class MyData
    {
        public int Id { get; set; }
        public DateTime HardDriveDateTime { get; set; }
        public decimal CurrentOpen { get; set; }
        public decimal CurrentHigh { get; set; }
        public decimal CurrentLow { get; set; }
        public decimal CurrentClose { get; set; }
        public string Direction { get; set; }
        public int Pressure { get; set; }
    }
}

然后我们原来的“var data = ...”代码变成了(也假设我们已经把它分成了它自己的另一个方法):

public IEnumerable<MyData> ReadTheData(string path)
{

var data = File.ReadAllLines(path)
  .Select(line => line.Split(','))
  .Select((cols, index) => new MyData {
    Id=index,
    HardDriveDateTime = DateTime.Parse(cols[0]),
    CurrentOpen = decimal.Parse(cols[1]),
    CurrentHigh = decimal.Parse(cols[2]),
    CurrentLow = decimal.Parse(cols[3]),
    CurrentClose = decimal.Parse(cols[4]),
    Direction = cols[5],
    Pressure  = int.Parse(cols[6])
});

return data;

}

在这里,我们在 new 关键字之后和第二个选择的 { 之前添加了“MyData”。这使得我们的 IEnumerable 类型为 MyData。我们可以写:

IEnumerable<MyData> data = ...

代替:

var data = ...

这些是相同的,我们让编译器为我们推断(在 Visual Studio 中,如果您将鼠标悬停在“数据”或 var 上,它会向您显示它推断为工具提示的类型)。

现在这是另一种单独的方法并已键入,我们可以在其他地方使用此方法,如下所示:

//...
   var theData = ReadTheData(@"c:\MyFolder\MyLogFile.txt");

// do something with the returned IEnumerable<MyData>
// for example chart this data using Data.Visualization.dll

    var series = new Series("Default");
    var area = new ChartArea("Default");
    var legend = new Legend("Default");

    var chart = new Chart();
    chart.Dock = DockStyle.Fill;

    chart.Series.Add(series);
    chart.ChartAreas.Add(area);
    series.ChartType = SeriesChartType.Bar;

    series.Points.DataBind(data, "Id", "Pressure", null);

    var form = new Form { Height = 800, Width = 1000 };
    form.Controls.Add(chart);
    form.Show();
}

或者您可以简单地迭代,或转到第一个、最后一个或查询此 IEnumerable,只要您认为合适。


推荐阅读