Hallo,
Ich habe ein Program mit dem ich Daten von einer WPF-App in einer .csv Datei einspeichere.
(Datum und dann ein paar int Werte).
Pro Tag sollte aber nur ein "Datensatz" in der Datei stehen das heißt wenn zb heute am 28.11.2018 der speichern button gedrückt wird, soll folgender datensatz hinzugefügt werden:
28:11:2018 00:00:00; 1;1;1;1;1
Das funktioniert perfekt.
Wenn aber heute schon ein Datensatz in der Datei abgespeichert wurde, sollen die Werte mit dem gleichen Datum addiert werden sodass nur noch eine einzelne Zeile da steht.
Das klappt auch sehr gut das einzige Problem ist das wenn ich zb:
28:11:2018 00:00:00; 1;1;1;1;1
28:11:2018 00:00:00; 1;1;1;1;1
Habe sollte
28:11:2018 00:00:00; 2;2;2;2;2
rauskommen.
Leider kommt logischerweise bei mir:
28:11:2018 00:00:00; 1;1;1;1;1
28:11:2018 00:00:00; 2;2;2;2;2
raus da ich den vorherigen Datensatz noch nicht gelöscht habe.
Da ich viel gegoogelt habe, weiß ich das es 2 Ansätze für die Lösung gibt:
Problem:
Ich sitze jetzt schon seit einer Woche an dem Problem (bin neu in c#) und würde gerne mal weiterkommen.
Wenn es geht würde ich eine Lösung ohne Linq bevorzugen aber zur Not nehme ich das dann ohne es zu verstehen und mache einfach weiter
Code:
class AddVariables
{
public static List<string[]> ReadCsvMethod()
{
List<string[]> oReadCsvList = new List<string[]>();
string filePath = (@"C: \Users\---\Desktop\---l\---\SaveDatei.csv");
using (StreamReader sr = new StreamReader(filePath))
{
while (!sr.EndOfStream)
{
string[] Line = sr.ReadLine().Split(';');
oReadCsvList.Add(Line);
}
}
return oReadCsvList;
}
public static Dictionary<DateTime, int[]> CompareDatimeTimeMethod(List<string[]> oReadCsvList, Dictionary<DateTime, int[]> oNewDataDictionary)
{
Dictionary<DateTime, int[]> oAddedOldAndNewDataDictionary = new Dictionary<DateTime, int[]>();
DateTime OldDateTime;
for (int i = 0; i < oReadCsvList.Count; i++)
{
if (DateTime.TryParse(oReadCsvList[i][0], out OldDateTime))
{
int[] iValuesToAdd = ConvertArrayMethod(oReadCsvList[i]);
if (OldDateTime.Date == DateTime.Now.Date)
{
for (int j = 0; j < iValuesToAdd.Length; j++)
{
oNewDataDictionary[OldDateTime][j] += iValuesToAdd[j];
}
}
}
}
return oNewDataDictionary;
}
private static int[] ConvertArrayMethod(string[] oZeileStringArray)
{
List<int> oConvertedArrayValuesList = new List<int>();
for (int i = 1; i < oZeileStringArray.Length; i++)
{
int iValue;
int.TryParse(oZeileStringArray[i], out iValue);
oConvertedArrayValuesList.Add(iValue);
}
return oConvertedArrayValuesList.ToArray();
}
Button zum speichern (In einer anderen Klasse):
private void btnSpeichern(object sender, RoutedEventArgs e)
{
Dictionary<DateTime, int[]> oNewDataDictionary = new Dictionary<DateTime, int[]>();
int[] iNewDataArray = new int[] { iVariable1, iVariable2, iVariable3, iVariable4, iVariable5};
List<string[]> oReadCsvList = AddVariables.ReadCsvMethod();
oNewDataDictionary.Add(DateTime.Now.Date, iNewDataArray);
using (FileStream fileStream = new FileStream(@"C: \Users\---\Desktop\---l\---\SaveDatei.csv", FileMode.Append, FileAccess.Write))
using (StreamWriter streamWriter = new StreamWriter(fileStream))
{
foreach (KeyValuePair<DateTime, int[]> kvp in AddVariables.CompareDatimeTimeMethod(oReadCsvList, oNewDataDictionary))
{
streamWriter.WriteLine("{0}; {1}", kvp.Key, string.Join(";", kvp.Value));
}
}
}
Mittels FileStream.Position kannst du auch gezielt zu einer Position in der Datei springen und dann anschließend die Werte überschreiben:
fileStream.Position = FileLength - csv[csv.Length-1].Length - Environment.NewLine.Length;
Oder besser noch mit FileStream.Seek vom Ende der Datei rückwärts springen.
Mittels
> kannst du auch gezielt zu einer Position in der Datei springen und dann anschließend die Werte überschreiben:fileStream.Position = FileLength - csv[csv.Length-1].Length - Environment.NewLine.Length;
Oder besser noch mit
> vom Ende der Datei rückwärts springen.
Okay das macht Sinn ich probiere gerade mit einem neuen Projekt und csv datei die "syntax" falls man das so sagt zu verstehen.
Ich versuche das Alphabet rückwärts zu lesen und den zweitletzten Buchstaben auszugeben.
Es hängt aber gerade an der ausgabe vielleicht kannst du mir kurz helfen:
using System;
using System.IO;
public class FSSeek
{
public static void Main()
{
// Alphabet.csv beeinhaltet "abcdefghijklmnopqrstuvwxyz"
using (FileStream fs = new FileStream(@"C:\Users\---\Desktop\---\Csvsave\Alphabet.csv", FileMode.Open, FileAccess.Read))
{
fs.Seek(fs.Length -2, SeekOrigin.Begin);
long test = fs.Length - 2;
{
Console.Write(test);
}
Console.ReadLine();
}
}
}
Wenn du aus der Datei lesen möchtest, dann mußt du selbstverständlich eine der Lese-Methoden aufrufen, z.B. FileStream.ReadByte.
Mit
long test = fs.Length - 2;
{
Console.Write(test);
}
gibst du ja nur die Position als Zahl aus (d.h. bei 26 Buchstaben in der Datei sollte 24 rauskommen).
Wenn du aus der Datei lesen möchtest, dann mußt du selbstverständlich eine der Lese-Methoden aufrufen, z.B.
> .
Genau bei mir kam vorhin 23 raus (Habe 25 Buchstaben).
Mein Problem ist ja das ich den Wert der Position von 23 (also y) nicht ausgeben kann bzw nicht weiß wie ich das machen würde.
Eigentlich hätte ich es mit foreach probiert aber das hat auch nicht wirklich funktioniert
Was paßt denn nicht, wenn du fileStream.ReadByte()
aufrufst?
Du mußt es nur noch für die Ausgabe in einen char
casten:
int data = fileStream.ReadByte();
Console.Write((char)data);
Vielen Dank hat geklappt.
Kannst du eventuell noch erklären warum man das (char) an der Stelle braucht ?
Da wegen dem Datentyp int
(als Rückgabewert der Methode) ja sonst das gelesene Byte als (ASCII bzw. Unicode)-Zahl ausgegeben würde, anstatt als Zeichen (char
).
Kannst es ja mal ohne den 'cast' probieren, dann sollte statt 'y' 121 ausgegeben werden, s.a. ASCII.
PS: Und Console.Write hat entsprechend der Datentypen unterschiedliche Überladungen, welche jeweils die Daten anders interpretieren und ausgeben. Generell wird dabei einfach deren ToString()
-Wert ausgegeben.
Da wegen dem Datentyp
int
(als Rückgabewert der Methode) ja sonst das gelesene Byte als (ASCII bzw. Unicode)-Zahl ausgegeben würde, anstatt als Zeichen (char
).
Der Rückgabetyp int hat primär nichts ASCII bzw. Unicode zu tun, denn -1 kennzeichnet das Ende eines Streams und dieser passt halt nicht in ein byte.
Siehe auch FileStream.ReadByte Method.
Ja, genau wegen der -1 (für den Fehlerfall) wird eben nicht ein byte
zurückgegeben, sondern eben der größere Datentyp int
. Und wenn nun ein Byte gelesen wurde (z.B. y
), wird eben bei der Ausgabe dieser Zahl dessen ASCII-Code ausgegeben.
Es ist nur ein wenig eigenartig, daß eine Methode namens ReadByte
ein int
anstatt byte
zurückgibt - und daher habe ich erklärt, was diese Zahl bedeutet:*-1: Fehler
*0 - 255: ASCII-Code des gelesenen Zeichens
Sonst würde ja auch der 'cast' nach char
nicht korrekt funktionieren (bei -1 kommt natürlich kein sinnvolles Zeichen raus, aber diesen Fall habe ich auch gar nicht berücksichtigt).
Hinweis: ReadByte auf char zu casten funktioniert nur für 255 Zeichen von etwas über eine Million in Unicode darstellbaren. Zugegeben, für die mit Abstand häufigsten, dennoch ist diese Vorgehensweise beim Arbeiten mit Text etwas, was einem potenziell das Genick bricht.
LaTino
"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)
Es ist schon klar, daß man Unicode-Texte mittels StreamReader lesen sollte.
@LaTino: ReadByte
liefert ja nur Werte im Bereich 0-255 (oder eben zusätzlich noch -1), aber niemals größere Werte (denn ein Byte sind nunmal nur 8 Bit 😉.
Es ging ja nur um die Frage:
Kannst du eventuell noch erklären warum man das (char) an der Stelle braucht ?
Und die habe ich beantwortet.
@Demokrit: Hast du es denn jetzt verstanden?
Es ist schon klar, daß man Unicode-Texte mittels
> lesen sollte.
Dir, ja 😉. Im Thread steht aber sinngemäß "man kann ein Zeichen per (char)ReadByte() auslesen." (Was in diesem Fall geht, ja.)
Deshalb der Hinweis, dass man da ganz schnell in Teufels Küche kommen kann.
"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)
Ja vielen dank für die Antworten 👍
Bitte keine Full Quotes: [Hinweis] Wie poste ich richtig?