【发布时间】:2018-03-23 14:37:47
【问题描述】:
我目前正在做一个小项目,但遇到了一个我目前无法解决的问题......
我有多个要读取的“.CSV”文件,它们都有相同的数据,只是值不同。
Header1;Value1;Info1
Header2;Value2;Info2
Header3;Value3;Info3
在阅读第一个文件时,我需要创建标题。问题是它们不是按列拆分而是按行拆分(如您在上面的 Header1-Header3 中看到的)。
然后它需要读取值 1 - 值 3(它们列在第 2 列中),除此之外,我需要创建另一个 Header -> Header4,其中包含始终放置在列中的“Info2”数据3 和第 2 行(第 3 列的其他值我可以忽略)。
所以第一个文件之后的结果应该是这样的:
Header1;Header2;Header3;Header4;
Value1;Value2;Value3;Info2;
在多个文件之后,它应该是这样的:
Header1;Header2;Header3;Header4;
Value1;Value2;Value3;Value4;
Value1b;Value2b;Value3b;Value4b;
Value1c;Value2c;Value3c;Value4c;
我用 OleDB 尝试过,但我得到了错误“缺少 ISAM”,我无法修复。我使用的代码如下:
public DataTable ReadCsv(string fileName)
{
DataTable dt = new DataTable("Data");
/* using (OleDbConnection cn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\"" +
Path.GetDirectoryName(fileName) + "\";Extendet Properties ='text;HDR=yes;FMT=Delimited(,)';"))
*/
using (OleDbConnection cn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
Path.GetDirectoryName(fileName) + ";Extendet Properties ='text;HDR=yes;FMT=Delimited(,)';"))
{
using(OleDbCommand cmd = new OleDbCommand(string.Format("select *from [{0}]", new FileInfo(fileName).Name,cn)))
{
cn.Open();
using(OleDbDataAdapter adapter = new OleDbDataAdapter(cmd))
{
adapter.Fill(dt);
}
}
}
return dt;
}
我做的另一个尝试是使用 StreamReader。但是标头在错误的位置,我不知道如何更改此+为每个文件执行此操作。我尝试的代码如下:
public static DataTable ReadCsvFilee(string path)
{
DataTable oDataTable = new DataTable();
var fileNames = Directory.GetFiles(path);
foreach (var fileName in fileNames)
{
//initialising a StreamReader type variable and will pass the file location
StreamReader oStreamReader = new StreamReader(fileName);
// CONTROLS WHETHER WE SKIP A ROW OR NOT
int RowCount = 0;
// CONTROLS WHETHER WE CREATE COLUMNS OR NOT
bool hasColumns = false;
string[] ColumnNames = null;
string[] oStreamDataValues = null;
//using while loop read the stream data till end
while (!oStreamReader.EndOfStream)
{
String oStreamRowData = oStreamReader.ReadLine().Trim();
if (oStreamRowData.Length > 0)
{
oStreamDataValues = oStreamRowData.Split(';');
//Bcoz the first row contains column names, we will poluate
//the column name by
//reading the first row and RowCount-0 will be true only once
// CHANGE TO CHECK FOR COLUMNS CREATED
if (!hasColumns)
{
ColumnNames = oStreamRowData.Split(';');
//using foreach looping through all the column names
foreach (string csvcolumn in ColumnNames)
{
DataColumn oDataColumn = new DataColumn(csvcolumn.ToUpper(), typeof(string));
//setting the default value of empty.string to newly created column
oDataColumn.DefaultValue = string.Empty;
//adding the newly created column to the table
oDataTable.Columns.Add(oDataColumn);
}
// SET COLUMNS CREATED
hasColumns = true;
// SET RowCount TO 0 SO WE KNOW TO SKIP COLUMNS LINE
RowCount = 0;
}
else
{
// IF RowCount IS 0 THEN SKIP COLUMN LINE
if (RowCount++ == 0) continue;
//creates a new DataRow with the same schema as of the oDataTable
DataRow oDataRow = oDataTable.NewRow();
//using foreach looping through all the column names
for (int i = 0; i < ColumnNames.Length; i++)
{
oDataRow[ColumnNames[i]] = oStreamDataValues[i] == null ? string.Empty : oStreamDataValues[i].ToString();
}
//adding the newly created row with data to the oDataTable
oDataTable.Rows.Add(oDataRow);
}
}
}
//close the oStreamReader object
oStreamReader.Close();
//release all the resources used by the oStreamReader object
oStreamReader.Dispose();
}
return oDataTable;
}
感谢所有愿意提供帮助的人。感谢您阅读本文!
此致
【问题讨论】:
-
您不需要驱动程序来读取 CSV 文件,在最简单的形式中,它们只是带有分隔符的文本文件。您可以一次读取一行并将其拆分。不过,您所描述的不是 CSV 文件。怎么会有人猜测
Value4用于不同的领域? -
如果标题和值没有混淆,您可以像包含 3 个字段一样读取文件,按 first/header 字段分组并将该键值用作字段名称,组值作为项目。请解释
Header4:Value4和忽略值背后的逻辑。这是一种可能只是看起来像 CSV 的格式吗? -
哦,这是我的错!值 4 不像值 1-3 只是我想阅读的另一个信息。对不起,我应该称之为“Info1”。我不需要来自第 3 列的任何信息,只需要这个信息“value4”其他我不介意的信息。让我在我的问题中解决这个问题所以这只是 CSV 本身中没有标题的另一个值。所以我需要在我的 DataTable 中为它创建一个新的 Header,称为 Header4
标签: c# csv datatable import-csv csvtotable