[英]Read CSV file in DataGridView
我想將 csv 文件讀入 Datagridview。 我想要一個類和一個函數,它可以像這樣讀取 csv:
class Import
{
public DataTable readCSV(string filePath)
{
DataTable dt = new DataTable();
using (StreamReader sr = new StreamReader(filePath))
{
string strLine = sr.ReadLine();
string[] strArray = strLine.Split(';');
foreach (string value in strArray)
{
dt.Columns.Add(value.Trim());
}
DataRow dr = dt.NewRow();
while (sr.Peek() >= 0)
{
strLine = sr.ReadLine();
strArray = strLine.Split(';');
dt.Rows.Add(strArray);
}
}
return dt;
}
}
並稱之為:
Import imp = new Import();
DataTable table = imp.readCSV(filePath);
foreach(DataRow row in table.Rows)
{
dataGridView.Rows.Add(row);
}
結果是-> 創建了行,但單元格中沒有數據!
public DataTable readCSV(string filePath)
{
var dt = new DataTable();
// Creating the columns
File.ReadLines(filePath).Take(1)
.SelectMany(x => x.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
.ToList()
.ForEach(x => dt.Columns.Add(x.Trim()));
// Adding the rows
File.ReadLines(filePath).Skip(1)
.Select(x => x.Split(';'))
.ToList()
.ForEach(line => dt.Rows.Add(line));
return dt;
}
在使用 foreach 循環的另一個版本下面
public DataTable readCSV(string filePath)
{
var dt = new DataTable();
// Creating the columns
foreach(var headerLine in File.ReadLines(filePath).Take(1))
{
foreach(var headerItem in headerLine.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
{
dt.Columns.Add(headerItem.Trim());
}
}
// Adding the rows
foreach(var line in File.ReadLines(filePath).Skip(1))
{
dt.Rows.Add(x.Split(';'));
}
return dt;
}
首先,我們使用 File.ReadLines,它返回一個 IEnumerable,它是行的集合。 我們使用 Take(1) 來獲取第一行,這應該是標題,然后我們使用 SelectMany 它將從 Split 方法返回的字符串數組轉換為單個列表,因此我們調用 ToList,我們現在可以使用 ForEach 方法在 DataTable 中添加列。
要添加行,我們仍然使用 File.ReadLines,但現在我們 Skip(1),這會跳過標題行,現在我們將使用 Select,創建一個Collection<Collection<string>>
,然后再次調用 ToList,最后調用 ForEach 在 DataTable 中添加行。 File.ReadLines 在 .NET 4.0 中可用。
Obs.: File.ReadLines不會讀取所有行,它返回一個 IEnumerable,並且行是惰性評估的,因此只會加載第一行兩次。
ReadLines 和 ReadAllLines 方法的區別如下: 使用 ReadLines 時,可以在返回整個集合之前開始枚舉字符串集合; 使用 ReadAllLines 時,必須等待返回整個字符串數組才能訪問該數組。 因此,當您處理非常大的文件時,ReadLines 會更有效率。
您可以使用 ReadLines 方法執行以下操作:
對文件執行 LINQ to Objects 查詢以獲取過濾后的行集。
使用 File.WriteAllLines(String, IEnumerable) 方法將返回的行集合寫入文件,或使用 File.AppendAllLines(String, IEnumerable) 方法將它們附加到現有文件。
創建一個立即填充的集合實例,該實例采用 IEnumerable 字符串集合作為其構造函數,例如 IList 或 Queue。
此方法使用 UTF8 作為編碼值。
如果您仍有任何疑問,請查看以下答案: File.ReadLines() 和 File.ReadAllLines() 有什么區別?
首先,安裝這個nuget包
PM> Install-Package CsvHelper
對於給定的 CSV,我們應該創建一個類來表示它
CSV 文件
Name;Age;Birthdate;Working
Alberto Monteiro;25;01/01/1990;true
Other Person;5;01/01/2010;false
類模型是
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public DateTime Birthdate { get; set; }
public bool Working { get; set; }
}
現在讓我們使用 CsvReader 來構建 DataTable
public DataTable readCSV(string filePath)
{
var dt = new DataTable();
var csv = new CsvReader(new StreamReader(filePath));
// Creating the columns
typeof(Person).GetProperties().Select(p => p.Name).ToList().ForEach(x => dt.Columns.Add(x));
// Adding the rows
csv.GetRecords<Person>().ToList.ForEach(line => dt.Rows.Add(line.Name, line.Age, line.Birthdate, line.Working));
return dt;
}
要在 DataTable e 中創建列,請使用一些反射,然后使用 GetRecords 方法在 DataTabble 中添加行
using Microsoft.VisualBasic.FileIO;
我建議以下。 它至少應該具有';'的優勢在一個字段中將被正確處理,並且它不限於特定的 csv 格式。
public class CsvImport
{
public static DataTable NewDataTable(string fileName, string delimiters, bool firstRowContainsFieldNames = true)
{
DataTable result = new DataTable();
using (TextFieldParser tfp = new TextFieldParser(fileName))
{
tfp.SetDelimiters(delimiters);
// Get Some Column Names
if (!tfp.EndOfData)
{
string[] fields = tfp.ReadFields();
for (int i = 0; i < fields.Count(); i++)
{
if (firstRowContainsFieldNames)
result.Columns.Add(fields[i]);
else
result.Columns.Add("Col" + i);
}
// If first line is data then add it
if (!firstRowContainsFieldNames)
result.Rows.Add(fields);
}
// Get Remaining Rows
while (!tfp.EndOfData)
result.Rows.Add(tfp.ReadFields());
}
return result;
}
}
CsvHelper 的作者在庫中構建功能。 代碼變得簡單:
using (var reader = new StreamReader("path\\to\\file.csv"))
using (var csv = new CsvReader(reader, CultureInfo.CurrentCulture))
{
// Do any configuration to `CsvReader` before creating CsvDataReader.
using (var dr = new CsvDataReader(csv))
{
var dt = new DataTable();
dt.Load(dr);
}
}
CultureInfo.CurrentCulture 用於確定默認分隔符,如果要讀取 Excel 保存的 csv,則需要。
我遇到了同樣的問題,但我找到了一種以我自己的方式使用@Alberto Monteiro的答案的方法......
我的 CSV 文件沒有“First-Line-Column-Header”,我個人出於某些原因沒有將它們放在那里,所以這是文件示例
1,john doe,j.doe,john.doe@company.net
2,jane doe,j.doe,jane.doe@company.net
所以你的想法對嗎?
現在,我將手動將Columns
添加到DataTable
。 而且我將使用Tasks
異步執行此操作。 並且只需使用foreach
循環使用以下函數將值添加到DataTable.Rows
中:
public Task<DataTable> ImportFromCSVFileAsync(string filePath)
{
return Task.Run(() =>
{
DataTable dt = new DataTable();
dt.Columns.Add("Index");
dt.Columns.Add("Full Name");
dt.Columns.Add("User Name");
dt.Columns.Add("Email Address");
// splitting the values using Split() command
foreach(var srLine in File.ReadAllLines(filePath))
{
dt.Rows.Add(srLine.Split(','));
}
return dt;
});
}
現在調用函數我只需ButtonClick
來完成這項工作
private async void ImportToGrid_STRBTN_Click(object sender, EventArgs e)
{
// Handling UI objects
// Best idea for me was to put everything a Panel and Disable it while waiting
// and after the job is done Enabling it
// and using a toolstrip docked to bottom outside of the panel to show progress using a
// progressBar and setting its style to Marquee
panel1.Enabled = false;
progressbar1.Visible = true;
try
{
DataTable dt = await ImportFromCSVFileAsync(@"c:\myfile.txt");
if (dt.Rows.Count > 0)
{
Datagridview1.DataSource = null; // To clear the previous data before adding the new ones
Datagridview1.DataSource = dt;
}
}
catch (Exception ex)
{
MessagBox.Show(ex.Message, "Error");
}
progressbar1.Visible = false;
panel1.Enabled = true;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.