首先,如果csv文件(例如:日期和价格)包含一些空单元格,当我尝试将数据存储在列表中时,如何解决此问题?
其次,一旦两个列表没问题,我想知道如何创建一个二维对象,例如PriceByDate[100,2]
(Date[100,0],Price[100,1
]),它可以存储来自csv文件的数据。
提前致谢
这是我的代码:(不工作)
var reader = new StreamReader(File.OpenRead(@"filenames"));
List<string> Dates = new List<string>();
List<string> Prices = new List<double>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(';');
listA.Add(values[0]);
listB.Add(values[1]);
}
DateTime[] s = Convert.ToDateTime(ListA.toArray());
double[] o = ListB.toArray();
object[,] PriceByDate = new object[,]{{s},{o}};
答案 0 :(得分:1)
首先,建议:
我建议使用免费的第三方CSV库,而不是重新发明轮子,除非有某种原因你不能。
http://joshclose.github.io/CsvHelper/
现在,答案是:
听起来你的问题是如何处理空单元格。首先,您需要确保每一行都是正确的长度,在CSV中,您至少会在每个单元格之间划分界限,即使它们是空的。 (注意:我在没有IDE的情况下长时间编写了所有这些代码,它可能不会按原样编译,可能会有错误。)
var line = reader.ReadLine();
var values = line.Split(';');
if (values.Count != numColumnsExpected)
{
throw new System.Exception("Expected " + numColumnsExpected + " columns, only found " + values.Count + " columns for a row.");
}
每列应具有预期类型,如果您想要彻底,可以为每列提供验证和处理功能。您可以将列号映射到字典中的函数。
private void ProcessorDelegate(string value);
Dictionary<int, ProcessorDelegate> m_processorMethods = new Dictionary<int, ProcessorDelegate>
{
{ 0, DateProcessor },
{ 1, PriceProcessor },
}
private void DateProcessor(string value)
{
// Make sure 'value' is a date
DateTime date;
if (!DateTime.TryParse(value, out date))
{
// If this field is required you could throw an exception here, or output a console error.
// This is the point at which you could check if 'value' was null or empty.
return;
}
// 'value' was a date, so add it to the DateTime[] array.
Dates.Add(date);
}
int numColumnsExpected = 6;
var Dates = new List<string>();
var Prices = new List<double>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(';');
if (values.Count != numColumnsExpected)
{
throw new System.Exception("Expected " + numColumnsExpected + " columns, only found " + values.Count + " columns for a row.");
}
// Sanity check, you must have a processor for each column
if (values.Count > m_processorMethods.Count)
{
throw new System.Exception("Expected " + numColumnsExpected + " processor methods, only found " + m_processorMethods.Count);
}
for (int i = 0; i < values.Count; ++i)
{
// Pass the value for a column to the processor that handles
// data for that column.
m_processorMethods[i](values[i]);
}
}
DateTime[] s=Convert.ToDateTime(ListA.toArray());
double[] o=ListB.toArray();
object[,] PriceByDate=new object[,]{{s},{o}} ;
}
警告:强>
将数据存储在一系列2D数组中,这些数组应该通过索引相互映射,非常脆弱。即使将其存储在2D对象数组中也不是非常有用,因为您需要转换这些对象以使用它们,并且您需要知道每列的顺序是什么数据类型无论如何要施放它们。
我强烈建议创建一个包含行数据的类。在该课程中,您可以存储日期,价格以及您需要的任何其他数据。然后你可以只有一个List或这些对象的数组,每个对象代表一行。
public class RowObject
{
public DateTime date;
public string price;
}
List<RowObject> m_rowData;
// A delegate that can take the RowObject
private void ProcessorDelegate(string value, RowObject currentRow);
// Pass in the RowObject to your processors
// The processor updates the RowObject with the processed information.
private void DateProcessor(string value, RowObject currentRow)
{
// Make sure 'value' is a date
DateTime date;
if (!DateTime.TryParse(value, out date))
{
// If this field is required you could throw an exception here, or output a console error.
// This is the point at which you could check if 'value' was null or empty.
return;
}
// 'value' was a date, so set this row's date
currentRow.date = date;
}
现在,一行的所有数据都很好地捆绑在一起,如果有空单元格,则该行的RowObject缺少该数据。您可以通过向RowObject添加验证方法来轻松验证行。
public class RowObject
{
public DateTime date;
public string price;
public bool IsValid()
{
if (date == null)
{
// Maybe output a warning to console here
return false;
}
if (string.IsNullOrEmpty(price))
{
// Maybe output a warning to console here
return false;
}
return true;
}
}
<强>最后强>
让我重申一下这一点,重新发明轮子,如果你使用CSVHelper库,我提供了一个链接,那么你不需要大部分代码。
答案 1 :(得分:1)
本文介绍如何使用ADO.net读取CSV文件。这很简单。使用此方法,您的日期和价格信息将在已配对的行/记录对象上。
文章:Reading CSV files in ADO.NET
如果您使用上述文章解决方案,您需要做的就是对记录字段进行简单的string.IsNullOrEmpty测试。如果函数返回true,则可以跳过行/记录。
我不确定这是否就像你在“2-D”对象中所寻找的那样。如果您需要在代码中创建一个对象,以便在从记录中读取数据后保存数据,我会使用类似的东西。另外,您可能还想使用小数来保存货币值。
public class PriceAndDate
{
public DateTime Date {get;set;}
public Decimal Price {get;set;}
}
List<PriceAndDate> priceAndDate = new List<PriceAndDate>();