0

我对 CSV 文件有疑问。我想跳过此时不相关的前几行并开始处理实际数据所在的文件。有没有跳过所有标题的方法?

这是我的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace bike
{
    public partial class Form1 : Form
    {
        public Form1()
        {

            InitializeComponent();

        }

        private void button1_Click(object sender, EventArgs e)
        {

            var col1 = new List<string>();
            var col2 = new List<string>();
            var col3 = new List<string>();
            var col4 = new List<string>();

            var Column1 = col1.Select<string, int>(q => Convert.ToInt32(q));
            var Column2 = col2.Select<string, int>(q => Convert.ToInt32(q));
            var Column3 = col3.Select<string, int>(q => Convert.ToInt32(q));
            var Column4 = col4.Select<string, int>(q => Convert.ToInt32(q));



            dataGridView1.Columns.Add("col1", "Heart Rate");
            dataGridView1.Columns.Add("col2", "Speed");
            dataGridView1.Columns.Add("col3", "Power");
            dataGridView1.Columns.Add("col4", "Altitude");



            DialogResult result = openFileDialog1.ShowDialog();
            if (result == DialogResult.OK)
            {
                using (StreamReader sr = new StreamReader(openFileDialog1.FileName))
                {

                    int row = 0;
                    string line;

                    bool isInHRData = false;

                    while ((line = sr.ReadLine()) !=null)
                    {
                        if (!isInHRData)
                        {
                            if (line != "[HRData]")
                                continue;
                            isInHRData = true;
                            continue;
                        }

                        else if (line.StartsWith("[") && line.EndsWith("["))
                            break;

                        string[] columns = line.Split('\t');
                        if (columns.Length > 0)
                            col1.Add(columns[0]);
                        if (columns.Length > 1)
                            col2.Add(columns[1]);
                        if (columns.Length > 2)
                            col3.Add(columns[2]);
                        if (columns.Length > 3)
                            col4.Add(columns[3]);



                        /*col1.Add(columns[0]);
                        col2.Add(columns[1]);
                        col3.Add(columns[2]);
                        col4.Add(columns[3]);
                         */

                        dataGridView1.Rows.Add();
                        for (int i = 0; i < columns.Length; i++)
                        {
                            dataGridView1[i, row].Value = columns[i];
                        }
                        row++; 
                    }

                    int maxSpeed = Column2.Max();
                    maxSpeed = maxSpeed / 10;
                    string MaxSpeed = Convert.ToString(maxSpeed);
                    textBox1.Text = MaxSpeed;

                    double aveSpeed = Column2.Average();
                    aveSpeed = aveSpeed / 10;
                    aveSpeed = Math.Round(aveSpeed, 0);
                    string AveSpeed = Convert.ToString(aveSpeed);
                    textBox2.Text = AveSpeed;

                    double aveHeart = Column1.Average();
                    aveHeart = Math.Round(aveHeart, 0);
                    string AveHeart = Convert.ToString(aveHeart);
                    textBox3.Text = AveHeart;

                    int maxHeart = Column1.Max();
                    string MaxHeart = Convert.ToString(maxHeart);
                    textBox4.Text = MaxHeart;

                    int minHeart = Column1.Min();
                    string MinHeart = Convert.ToString(minHeart);
                    textBox5.Text = MinHeart;

                    double avePower = Column3.Average();
                    avePower = Math.Round(avePower, 0);
                    string AvePower = Convert.ToString(avePower);
                    textBox6.Text = AvePower;

                    int maxPower = Column3.Max();
                    string MaxPower = Convert.ToString(maxPower);
                    textBox7.Text = MaxPower;

                    double aveAltitude = Column4.Average();
                    aveAltitude = Math.Round(aveAltitude, 0);
                    string AveAltitude = Convert.ToString(aveAltitude);
                    textBox8.Text = AveAltitude;

                    int maxAltitude = Column4.Max();
                    string MaxAltitude = Convert.ToString(maxAltitude);
                    textBox9.Text = MaxAltitude;


                }
            }

        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
    }
}

以及 CSV 文件的示例(HRData 位是我唯一需要显示的位,因此我想忽略所有其余的位):

[Params]
Version=106
Monitor=34
SMode=111000100
Date=20101110
StartTime=13:47:00.0
Length=02:07:41.7
Interval=5
Upper1=150
Lower1=140
Upper2=0
Lower2=0
Upper3=180
Lower3=177
Timer1=00:00:00.0
Timer2=00:00:00.0
Timer3=00:00:00.0
ActiveLimit=0
MaxHR=195
RestHR=48
StartDelay=0
VO2max=54
Weight=0

[Note]

[IntTimes]
00:01:23.7  139 0   118 139
0   0   0   290 75  69
0   0   0   0   0
0   444 0   70  0   0
0   0   0   0   0   0
00:30:51.4  157 0   145 158
0   0   0   372 133 2
0   0   0   0   0
0   16020   0   90  0   0
0   0   0   0   0   0
01:04:46.0  148 0   146 157
0   0   0   245 118 11
0   0   0   0   0
0   32000   0   80  0   0
0   0   0   0   0   0
01:34:33.7  138 0   144 152
0   0   0   336 116 32
0   0   0   0   0
0   46524   0   70  0   0
0   0   0   0   0   0
02:06:40.4  145 0   144 160
0   0   0   253 130 60
0   0   0   0   0
0   60432   0   60  0   0
0   0   0   0   0   0
02:07:41.7  119 0   129 145
0   0   0   0   75  55
0   0   0   0   0
0   60791   0   60  0   0
0   0   0   0   0   0

[IntNotes]
1   
2   
3   
4   
5   
6   

[ExtraData]

[LapNames]
1   0   
2   0   
3   0   
4   0   
5   0   
6   0   

[Summary-123]
7660    0   820 5995    845 0
195 150 140 48
7660    0   820 5995    845 0
195 0   0   48
0   0   0   0   0   0
195 0   0   48
0   1532

[Summary-TH]
7660    0   7660    0   0   0
195 0   0   48
0   1532

[HRZones]
195
176
156
137
117
98
0
0
0
0
0

[SwapTimes]

[Trip]
607
329
7661
15
70
286
494
4720

[HRData]
91  161 0   64
91  159 0   64
98  225 56  63
105 260 68  63
106 183 70  63
101 52  55  63
104 119 29  63
110 153 32  63
118 161 42  64
124 113 43  65
123 77  38  66
125 189 32  66
129 248 64  66
134 272 73  66
137 271 75  67
137 270 73  67
4

2 回答 2

3

试试这个代码:

...
int row = 0;
string line;
bool isInHRData = false;

while ((line = sr.ReadLine()) !=null)
{
    if (!inHRData)
    {
         if (line == "[HRData]")
              isInHRData = true;
         continue;
    } 
    ....

如果还有其他部分 AFTER HRData,请添加以下代码:

...
int row = 0;
string line;
bool isInHRData = false;

while ((line = sr.ReadLine()) !=null)
{
    if (!inHRData)
    {
         if (line == "[HRData]")
              isInHRData = true;
         continue;
    } 
    else if (line.StartsWith("[") && line.EndsWith("[")) // This criteria can be mucht better, checking for words, etc. but you in essence this will work.
        break;
    ....

对于 IndexOutOfRangeException:

string[] columns = line.Split('\t');
if (columns.Length > 0)
     col1.Add(columns[0]);
if (columns.Length > 1)
     col2.Add(columns[1]);
if (columns.Length > 2)
     col3.Add(columns[2]);
if (columns.Length > 3)
     col4.Add(columns[3]);
于 2013-04-28T14:15:18.097 回答
1

由于其余代码中出现的其他小错误,我建议您进行重构。这个例子没有重构,它是完全重写的。我将逻辑与用户界面分开。这总是一件好事。它使您可以将逻辑迁移到其他类型的应用程序,例如 WPF 的 Web 应用程序。

此代码完全基于职责分离:

  • HRData:实体,代码的主要参与者。您的基本数据。实体比 int-array 更好,因为属性赋予了更多意义。
  • HRDataExtensions:统计方法,负责做计算。
  • HRDataReader:负责读取一个文件,并读入一个HRData列表。

使用此 HRData 列表,您可以填充您的 UI 表单。

public class HRData
{
    public int? HeartRate
    {
        get;
        set;
    }
    public int? Speed
    {
        get;
        set;
    }
    public int? Power
    {
        get;
        set;
    }
    public int? Altitude
    {
        get;
        set;
    }

    public override string ToString()
    {
        return String.Format("Heart rate={0}, Speed={1}, Power={2}, Altitude={3}", HeartRate, Speed, Power, Altitude);
    }
}

public static class HRDataExtensions
{
    static private int? CalculateInt32(this IEnumerable<HRData> data, Func<HRData, int?> valueSelector, Func<IEnumerable<int?>, int?> aggregation)
    {
        List<int?> list = new List<int?>();
        list.AddRange(data.Select(valueSelector));
        return aggregation(list);
    }

    static private int? CalculateDouble(this IEnumerable<HRData> data, Func<HRData, int?> valueSelector, Func<IEnumerable<int?>, double?> aggregation)
    {
        List<int?> list = new List<int?>();
        list.AddRange(data.Select(valueSelector));
        double? result = aggregation(list);
        return (result == null) ? null : (int?)Math.Round(result.Value);
    }

    static public int? MinimumHeartRate(this IEnumerable<HRData> data)
    {
        return data.CalculateInt32(hr => hr.HeartRate, Enumerable.Min);
    }

    static public int? MaximumHeartRate(this IEnumerable<HRData> data)
    {
        return data.CalculateInt32(hr => hr.HeartRate, Enumerable.Max);
    }

    static public int? AverageHeartRate(this IEnumerable<HRData> data)
    {
        return data.CalculateDouble(hr => hr.HeartRate, Enumerable.Average);
    }

    static public int? MinimumSpeed(this IEnumerable<HRData> data)
    {
        return data.CalculateInt32(hr => hr.Speed, Enumerable.Min);
    }

    static public int? MaximumSpeed(this IEnumerable<HRData> data)
    {
        return data.CalculateInt32(hr => hr.Speed, Enumerable.Max);
    }

    static public int? AverageSpeed(this IEnumerable<HRData> data)
    {
        return data.CalculateDouble(hr => hr.Speed, Enumerable.Average);
    }

    static public int? MinimumPower(this IEnumerable<HRData> data)
    {
        return data.CalculateInt32(hr => hr.Power, Enumerable.Min);
    }

    static public int? MaximumPower(this IEnumerable<HRData> data)
    {
        return data.CalculateInt32(hr => hr.Power, Enumerable.Max);
    }

    static public int? AveragePower(this IEnumerable<HRData> data)
    {
        return data.CalculateDouble(hr => hr.Power, Enumerable.Average);
    }

    static public int? MinimumAltitude(this IEnumerable<HRData> data)
    {
        return data.CalculateInt32(hr => hr.Altitude, Enumerable.Min);
    }

    static public int? MaximumAltitude(this IEnumerable<HRData> data)
    {
        return data.CalculateInt32(hr => hr.Altitude, Enumerable.Max);
    }

    static public int? AverageAltitude(this IEnumerable<HRData> data)
    {
        return data.CalculateDouble(hr => hr.Altitude, Enumerable.Average);
    }
}

public static class HRDataReader
{
    static private int? ConvertValue(string[] values, int index)
    {
        if (index >= values.Length)
            return null;
        int value;
        if (int.TryParse(values[index], out value))
            return value;
        return null;
    }

    static public IList<HRData> Read(string fileName)
    {
        if (string.IsNullOrEmpty(fileName))
            throw new ArgumentNullException("fileName");
        using (StreamReader sr = new StreamReader(fileName))
        {
            string line;

            // First: Skip to the correct section.
            while ((line = sr.ReadLine()) != null)
                if (line == "[HRData]")
                    break;

            // Now: Read the HRData
            List<HRData> data = new List<HRData>();
            while ((line = sr.ReadLine()) != null)
            {
                if (line.StartsWith("[") && line.EndsWith("]"))
                    break;
                line = line.Trim().Replace("\t", " "); // Remove all tabs.
                while (line.Contains("  ")) // Remove all duplicate spaces.
                    line = line.Replace("  ", " ");
                string[] values = line.Split(' '); // Split the line up.
                data.Add(new HRData
                {
                    HeartRate = ConvertValue(values, 0),
                    Speed = ConvertValue(values, 1),
                    Power = ConvertValue(values, 2),
                    Altitude = ConvertValue(values, 3)
                });
            }
            return data;
        }
    }
}

编辑

现在你可以像这样调整你的代码:

    private void button1_Click(object sender, EventArgs e)
    {
        if (openFileDialog1.ShowDialog() == DialogResult.OK)
        {
            dataGridView1.Rows.Clear();
            dataGridView1.Columns.Clear();

            IList<HRData> data = HRDataReader.Read(openFileDialog1.FileName);

            dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { Name = "HeartRate", HeaderText = "Heart rate", DataPropertyName = "HeartRate" });
            dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { Name = "Speed", HeaderText = "Speed", DataPropertyName = "Speed" });
            dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { Name = "Power", HeaderText = "Power", DataPropertyName = "Power" });
            dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { Name = "Altitude", HeaderText = "Altitude", DataPropertyName = "Altitude" });

            dataGridView1.DataSource = data;

            label1.Text = data.MaximumAltitude().ToString();

            textBox1.Text = data.MaximumSpeed().ToString();
            textBox2.Text = data.AverageSpeed().ToString();
            textBox3.Text = data.AverageHeartRate().ToString();
            textBox4.Text = data.MaximumHeartRate().ToString();
            textBox5.Text = data.MinimumHeartRate().ToString();
            textBox6.Text = data.AveragePower().ToString();
            textBox7.Text = data.MaximumPower().ToString();
            textBox8.Text = data.AverageAltitude().ToString();
            textBox9.Text = data.MaximumAltitude().ToString();
        }
    }
于 2013-04-28T16:29:46.513 回答