在C#中实时导入数据的最佳方式

时间:2017-04-22 17:18:53

标签: c#

我有一个小项目,我已经为一个独立的学习班学习了一段时间。我应该导入大约140,000个数据点进行基于IDW的数学分析,目前程序需要大约10~14分钟来导入我的所有点。

我正在做的是读取.txt文件,基于新行拆分,然后根据字段之间的空格拆分未来。然后将它们转换为我设计的Datapt对象,以便于OOD风格操作。

所有我想知道的是,我可能不得不使用该程序进行现场演示,我不希望人们在预加载时必须坐在那里14分钟,如果推动我可以找到来自朋友的笔记本电脑(我的主要功能是dekstop)并在我的演示之前预先加载它,但整个问题让我想知道为什么加载只有100k数据片需要这么长时间?我想这会花费更短的时间?如果有比任何人都知道的更快的方式,如果你可以分享它,将不胜感激!

private void openPointsToolStripMenuItem_Click(object sender, EventArgs e)
    {
        openFileDialog1.Filter = "Text files|*.txt|All files|*.*";
        openFileDialog1.Title = "Open the Captured Packets";
        openFileDialog1.ShowDialog();

        //Check to see if a filename was given

        if (openFileDialog1.FileName != "")
        {
             readOut = System.IO.File.ReadAllText(openFileDialog1.FileName);
            //textBox1.Text = System.IO.File.ReadAllText(openFileDialog1.FileName);
            dataChain = readOut.Split(new String[] { "\r\n", "\n" }, StringSplitOptions.None);

            //Read out Code
            string[] link; //dataChain[0].Split(null);



            for(int i = 0; i < 100000; i++)
            {
                link = dataChain[i].Split(null);
                textBox1.AppendText(link[0] + "         " + link[1] + "         " + link[2] + "         "+ link[3] + "\r\n");
                dataPt Temp = new dataPt(Convert.ToDouble(link[0]), Convert.ToDouble(link[1]), Convert.ToDouble(link[2]), Convert.ToDouble(link[3]));

                dataList.Add(Temp);
                ptDisplay.Items.Add(Temp.ToString());

            }
        }
    }

2 个答案:

答案 0 :(得分:0)

我想到的一个改进是,您不需要将整个文件加载到内存中。您可以使用ReadLines方法逐行处理它,该方法返回Enumerable<string>,您可以使用Take扩展方法进一步过滤结果:

private void openPointsToolStripMenuItem_Click(object sender, EventArgs e)
{
    openFileDialog1.Filter = "Text files|*.txt|All files|*.*";
    openFileDialog1.Title = "Open the Captured Packets";
    openFileDialog1.ShowDialog();

    if (openFileDialog1.FileName != "")
    {
        foreach (string line in System.IO.File.ReadLines(openFileDialog1.FileName).Take(100000))
        {
            var link = line.Split(null);
            textBox1.AppendText(link[0] + "         " + link[1] + "         " + link[2] + "         "+ link[3] + "\r\n");
            dataPt Temp = new dataPt(Convert.ToDouble(link[0]), Convert.ToDouble(link[1]), Convert.ToDouble(link[2]), Convert.ToDouble(link[3]));
            dataList.Add(Temp);
            ptDisplay.Items.Add(Temp.ToString());
        }
    }
}

答案 1 :(得分:0)

不要一次将文本全部加载到内存中。而是使用内部循环中的File.ReadLines枚举行并逐个处理它们,但不更改每行的TextBox.Text也非常重要。这在执行和内存占用方面都非常昂贵。 (字符串是不可变的,所以在每个循环中,一个新的字符串在内存中分配,而前一个字符串就是内存碎片造成的破坏)

StringBuilder sb = new StringBuilder();
foreach(string line in File.ReadLines(openFileDialog1.FileName))
{
    link = line.Split();
    sb.AppendLine(link[0] + "         " + link[1] + "         " + link[2] + "         "+ link[3]);
    dataPt Temp = new dataPt(Convert.ToDouble(link[0]), Convert.ToDouble(link[1]), Convert.ToDouble(link[2]), Convert.ToDouble(link[3]));
    dataList.Add(Temp);
    ptDisplay.Items.Add(Temp.ToString());
}
textBox1.AppendText(sb.ToString());

而是将每一行添加到一个StringBuilder class,它比一个TextBox.Text属性更好地处理连接在一起的字符串。然后在退出循环时,只更改TextBox.Text一次。