我有一个C#程序,它正在拉入一个大约42000行长的.csv文件。文件中的所有数据存储如下:
Zipcode,City,State
我将所有信息拉入listview
中的三个不同列中。
目前,这些数据大约需要30-50秒才能进入我的程序。我的问题是如何更好地优化我的代码以减少这段时间?
以下是我的代码片段。注释的代码是我以前尝试过的代码,但在减少时间方面没有成功,因此我以更容易阅读的方式重写了它。
//These are globally declared.
lvZip.Columns.Add("Zipcode", 150, HorizontalAlignment.Left);
lvZip.Columns.Add("City", 150, HorizontalAlignment.Left);
lvZip.Columns.Add("State", 150, HorizontalAlignment.Left);
lvZip.View = View.Details;
lvZip.Items.Clear();
//string dir = System.IO.Path.GetDirectoryName(
// System.Reflection.Assembly.GetExecutingAssembly().Location);
//string path = dir + @"zip_code_database_edited.csv";
//var open = new StreamReader(File.OpenRead(path));
//foreach (String s in File.ReadAllLines(path))
//{
// Zipinfo = s.Split(',');
// Zipinfo[0] = Zipinfo[0].Trim();
// Zipinfo[1] = Zipinfo[1].Trim();
// Zipinfo[2] = Zipinfo[2].Trim();
// lvItem = new ListViewItem(Zipinfo);
// lvZip.Items.Add(lvItem);
//}
//open.Close();
StreamReader myreader = File.OpenText(path);
aLine = myreader.ReadLine();
while (aLine != null)
{
Zipinfo = aLine.Split(',');
Zipinfo[0] = Zipinfo[0].Trim();
Zipinfo[1] = Zipinfo[1].Trim();
Zipinfo[2] = Zipinfo[2].Trim();
lvItem = new ListViewItem(Zipinfo);
lvZip.Items.Add(lvItem);
aLine = myreader.ReadLine();
}
myreader.Close();
您应该在向ListView添加任何内容之前和之后使用ListView.BeginUpdate()
和ListView.EndUpdate()
。第二件事是使用ListView.AddRange()
而不是ListView.Add()
。通过使用Add方法,您每次使用ListView时都会重新绘制它。但是,使用ListView.AddRange()
,您只会重新绘制一次。这应该会为您优化一点。
您可以尝试:
lvZip.BeginUpdate();
然后再开始添加所有项目。
然后:
lvZip.EndUpdate();
当你完成。
这将阻止控件在添加每个项目时绘制该项目,从而使整个过程非常缓慢。
黄金法则:不要使用String.Split()读取CSV数据
.NET框架已经有一个名为TextFieldParser
的内置专用CSV解析器。
它位于Microsoft.VisualBasic.FileIO
命名空间中。
String.Split()
不仅没有正确处理许多边缘情况,而且使用StreamReader
的速度也慢得多。
最后一句话:一个技巧是使用using
语句,以确保您的一次性对象得到释放(释放非托管资源)。我看到你没有在上面的代码中使用它们(双关语并非有意)。
实际上,这并没有超出这个问题的范围,因为高效的内存管理可以提高代码的性能。
也许还有一些工作要做,但使用带有文本文件的DataGridView作为数据源,您可以在2秒内获得加载时间。,来自42000行.csv。下面是一些代码:
private void button2_Click(object sender, EventArgs e)
{
string errorInfo = String.Empty;
//open text file into Dataset:
string textFilePath = @"textfile1.csv";
DataSet dataTextFile = new DataSet("textfile");
if(!LoadTextFile(textFilePath, dataTextFile, out errorInfo))
{
MessageBox.Show("Failed to load text file:n" + errorInfo,
"Load Text File");
return;
}
dgTextFile.DataSource = dataTextFile.Tables[0];
dataTextFile.Dispose();
}
private bool LoadTextFile(string textFilePath, DataSet dataToLoad, out string errorInfo)
{
errorInfo = String.Empty;
try
{
string textFileFolder = (new System.IO.FileInfo(textFilePath)).DirectoryName;
string textConnectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;" +
"Data Source=" + textFileFolder + ";" +
"Extended Properties="text;";";
OleDbConnection textConnection = new OleDbConnection(textConnectionString);
textConnection.Open();
textFilePath = (new System.IO.FileInfo(textFilePath)).Name;
string selectCommand = "select * from " + textFilePath;
//open command:
OleDbCommand textOpenCommand = new OleDbCommand(selectCommand);
textOpenCommand.Connection = textConnection;
OleDbDataAdapter textDataAdapter = new OleDbDataAdapter(textOpenCommand);
int rows = textDataAdapter.Fill(dataToLoad);
textConnection.Close();
textConnection.Dispose();
return true;
}
catch(Exception ex_load_text_file)
{
errorInfo = ex_load_text_file.Message;
return false;
}
}
其中一些代码来自MSDN示例,但我似乎找不到该页面。