C#在.csv文件中添加具有相同Date.Time的行



我目前正在制作一个程序,用于跟踪某些内容(基本INT值和保存日期(。

我的目标是将具有相同日期的INT值相加。

20.11.2018 00:00:00; 1;1;1;1;1
20.11.2018 00:00:00; 1;1;1;1;1
22.11.2018 00:00:00; 1;1;1;1;1

基本上应该看起来像这个

20.11.2018 00:00:00; 2;2;2;2;2
22.11.2018 00:00:00; 1;1;1;1;1

保存数据,甚至将两条"行"添加在一起都非常好。

问题是,当我把行加在一起时,带有1的2行显然不会被删除。

这是比较日期并将行相加的方法:

public static Dictionary<DateTime, int[]> CompareDateMethod(Dictionary<DateTime, int[]> oDateTimeAndIntDictionary,string[][] ReadData)
{
Dictionary<DateTime, int[]> oPrintRealData = new Dictionary<DateTime, int[]>();
Dictionary<DateTime, int[]> oAddRealData = new Dictionary<DateTime, int[]>();
for (int i = 0 ; i < ReadData.Length; i++)
{
DateTime dtDateValue;
if (DateTime.TryParse(ReadData[i][0], out dtDateValue))     
{
int[] iValuesToAdd = ConvertArrayToInt(ReadData[i]);
if (dtDateValue.Date == DateTime.Now.Date)                   
{
for (int j = 0; j < iValuesToAdd.Length; j++)
{
oDateTimeAndIntDictionary[dtDateValue.Date][j] += iValuesToAdd[j];      
}
}
else if (dtDateValue.Date != DateTime.Now.Date)                              
{
goto Endloop;                                   
}
}
}
Endloop:
return oDateTimeAndIntDictionary;  

这是将数据写入.CSV文件的方法

Dictionary<DateTime, int[]> oDateTimeAndIntDictionary = new Dictionary<DateTime, int[]>();
string[][] OldData= AddVariables.ReadOldData();
int[] iNewDataArray = new int[] { iVariable1, iVariable2, iVariable3, iVariable4, iVariable5};
oDateTimeAndIntDictionary.Add(DateTime.Now.Date, iNewDataArray);
using (System.IO.FileStream fileStream = new System.IO.FileStream(@"C: Users---CsvsaveSaveDatei.csv", System.IO.FileMode.Append, System.IO.FileAccess.Write))
using (System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(fileStream))
{
foreach (KeyValuePair<DateTime, int[]> kvp in AddVariables.CompareDateMethod(oDateTimeAndIntDictionary, OldData))
{
streamWriter.WriteLine("{0}; {1}", kvp.Key, string.Join(";", kvp.Value));
}
}

我非常努力地想出一些东西,但什么都不起作用(我试着从.csv中删除行,这似乎真的很难,我试着向后读取文件,但不起作用等等(

如果有人能给我一些建议,我将非常感激。

我认为原始代码的问题在于它对什么时候发生有点困惑。我对它进行了重新构造,使事情按逻辑顺序发生(并对它做了一些更新,简化了变量名等(。有一个函数用于组合具有相同日期的行,它与CSV编写代码(没有改变(是分开的

static void Main(string[] args)
{
var oldData = ReadOldData();
// Do the work
var results = SumValuesForSameDate(oldData);
// Write the file
using (System.IO.FileStream fileStream = new System.IO.FileStream(@"C: Users---CsvsaveSaveDatei.csv", System.IO.FileMode.Append, System.IO.FileAccess.Write))
using (System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(fileStream))
{
foreach (KeyValuePair<DateTime, int[]> kvp in results)
{
streamWriter.WriteLine("{0}; {1}", kvp.Key, string.Join(";", kvp.Value));
}
}
}
public static Dictionary<DateTime, int[]> SumValuesForSameDate(string[][] readData)
{
var oDateTimeAndIntDictionary = new Dictionary<DateTime, int[]>();
var currentDate = DateTime.MinValue;
foreach (var row in readData)
{
DateTime dateValue;
if(!DateTime.TryParse(row[0], out dateValue)) continue;
dateValue = dateValue.Date;
var intValues = ConvertArrayToInt(row);
if (dateValue == currentDate)
{
for (var j = 0; j < intValues.Length; j++)
{
oDateTimeAndIntDictionary[dateValue][j] += intValues[j];
}
}
else
{
oDateTimeAndIntDictionary.Add(dateValue, intValues);
currentDate = dateValue;
}
}
return oDateTimeAndIntDictionary;
}
static int[] ConvertArrayToInt(string[] strings)
{
var output = new int[strings.Length - 1];
for (var i = 1; i < strings.Length; i++)
{
output[i - 1] = int.Parse(strings[i]);
}
return output;
}
static string[][] ReadOldData()
{
// Fake data
var data = new string[][]
{
new string[] { "20.11.2018 00:00:00", "1", "1", "1", "1", "1"  },
new string[] { "20.11.2018 00:00:00", "1", "1", "1", "1", "1"  },
new string[] { "22.11.2018 00:00:00", "1", "1", "1", "1", "1"  },
};
return data;
}
}

要覆盖以前的CSV,只需使用System.IO.FileMode.Create而不是Append。这将覆盖以前的任何数据。

您需要以任何方式覆盖csv以清除已写入的行。因此,返回ReadData并覆盖ReadData的解析值,而不是从CompareDateMethod方法返回oDateTimeAndIntDictionary

像这样的

public static Dictionary<DateTime, int[]> CompareDateMethod(Dictionary<DateTime, int[]> oDateTimeAndIntDictionary,string[][] ReadData)
{
Dictionary<DateTime, int[]> oPrintRealData = new Dictionary<DateTime, int[]>();
Dictionary<DateTime, int[]> oAddRealData = new Dictionary<DateTime, int[]>();
for (int i = 0 ; i < ReadData.Length; i++)
{
DateTime dtDateValue;
if (DateTime.TryParse(oDateTimeAndIntDictionary[0][0], out dtDateValue))     
{
int[] iValuesToAdd = ConvertArrayToInt(ReadData[i]);
if (dtDateValue.Date == DateTime.Now.Date)                   
{
for (int j = 0; j < iValuesToAdd.Length; j++)
{
//Add the ReadData values here and store at ReadData[i][j]
}
}
else if (dtDateValue.Date != DateTime.Now.Date)                              
{
goto Endloop;                                   
}
}
}
Endloop:
return ReadData;
}

希望这能帮助。。。

我读过你关于不使用linq和第三部分lib的评论太晚了
但让我给你看看你缺了什么
这是一个小小的Linq+CSVHelper

首先,避免定义您的数据,并定义如何在CSV 中映射它们

public sealed class data
{
public DateTime TimeStamp { get; set; }
public List<int> Numbers { get; set; }
}
public sealed class dataMapping : ClassMap<data>
{
public dataMapping()
{
Map(m => m.TimeStamp).Index(0);
Map(m => m.Numbers)
.ConvertUsing(
row =>
new List<int> {
row.GetField<int>(1),
row.GetField<int>(2),
row.GetField<int>(3)
}
);
}
}

现在这是一个简短的演示:

class CsvExemple
{
string inputPath = "datas.csv";
string outputPath = "datasOut.csv";
List<data> datas;
public void Demo()
{
//no duplicate row in orginal input
InitialiseFile();
LoadExistingData();
//add some new row and some dupe
NewDatasArrived();
//save to an other Path, to Compare. 
SaveDatas();
}
private void SaveDatas()
{
using (TextWriter writer = new StreamWriter(outputPath))
using (var csvWriter = new CsvWriter(writer))
{
csvWriter.Configuration.RegisterClassMap<dataMapping>();
csvWriter.Configuration.Delimiter = ";";
csvWriter.Configuration.HasHeaderRecord = false;
csvWriter.WriteRecords(datas);
}
}
static List<int> SuperZip(params List<int>[] sourceLists)
{
for (var i = 1; i < sourceLists.Length; i++)
{
sourceLists[0] = sourceLists[0].Zip(sourceLists[i], (a, b) => a + b).ToList();
}
return sourceLists[0];
}
private void NewDatasArrived()
{
var now = DateTime.Today;
// New rows
var outOfInitialDataRange = Enumerable.Range(11, 15)
.Select(x => new data { TimeStamp = now.AddDays(-x), Numbers = new List<int> { x, x, x } });
// Duplicate rows
var inOfInitialDataRange = Enumerable.Range(3, 7)
.Select(x => new data { TimeStamp = now.AddDays(-x), Numbers = new List<int> { x, x, x } });
//add all of them them together
datas.AddRange(outOfInitialDataRange);
datas.AddRange(inOfInitialDataRange);
// all this could have been one Line
var grouped = datas.GroupBy(x => x.TimeStamp);
var temp = grouped.Select(g => new { TimeStamp = g.Key, ManyNumbers = g.Select(x => x.Numbers).ToArray() });
// We can combine element of 2 list using Zip. ListA.Zip(ListB, (a, b) => a + b)
datas = temp.Select(x => new data { TimeStamp = x.TimeStamp, Numbers = SuperZip(x.ManyNumbers) }).ToList();
}
private void LoadExistingData()
{
if (File.Exists(inputPath))
{
using (TextReader reader = new StreamReader(inputPath))
using (var csvReader = new CsvReader(reader))
{
csvReader.Configuration.RegisterClassMap<dataMapping>();
csvReader.Configuration.HasHeaderRecord = false;
csvReader.Configuration.Delimiter = ";";
datas = csvReader.GetRecords<data>().ToList();
}
}
else
{
datas = new List<data>();
}
}
private void InitialiseFile()
{
if (File.Exists(inputPath))
{
return;
}
var now = DateTime.Today;
var ExistingData = Enumerable.Range(0, 10)
.Select(x => new data { TimeStamp = now.AddDays(-x), Numbers = new List<int> { x, x, x } });
using (TextWriter writer = new StreamWriter(inputPath))
using (var csvWriter = new CsvWriter(writer))
{
csvWriter.Configuration.RegisterClassMap<dataMapping>();
csvWriter.Configuration.Delimiter = ";";
csvWriter.Configuration.HasHeaderRecord = false;
csvWriter.WriteRecords(ExistingData);
}
}
}

最新更新