myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Grundlagen von C# » Vorletzte Zeile in einer CSV-Datei löschen
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Vorletzte Zeile in einer CSV-Datei löschen

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
Demokrit
myCSharp.de-Mitglied

Dabei seit: 20.11.2018
Beiträge: 10


Demokrit ist offline

Vorletzte Zeile in einer CSV-Datei löschen

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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:

Code:
1:
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:

Code:
1:
2:
28:11:2018 00:00:00; 1;1;1;1;1
28:11:2018 00:00:00; 1;1;1;1;1

Habe sollte

Code:
1:
28:11:2018 00:00:00; 2;2;2;2;2

rauskommen.

Leider kommt logischerweise bei mir:

Code:
1:
2:
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:

1. Jedes mal die .csv komplett neu schreiben statt zu "appenden" um dann den einen Datensatz auszulassen
2. Jedes mal die 2 letzte Zeile löschen, da diese ja in dem hinzugefügten Datensatz steht

Problem:

1. Ich verstehe das Prinzip dahinter und es scheint mir die "sauberere" Lösung zu sein, aber ich verstehe nicht wie ich in dem Fall immer die 2t letzte Zeile (Die immer einen Unterschiedlichen Wert hat) "rausfiltern" sollte.
2. Ich verstehe bzw weiß nicht ob das möglich ist

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:

C#-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):

C#-Code:
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));
                }
            }
        }
28.11.2018 09:36 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Th69
myCSharp.de-Poweruser/ Experte

avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 3.388
Entwicklungsumgebung: Visual Studio 2015/17


Th69 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Mittels  FileStream.Position kannst du auch gezielt zu einer Position in der Datei springen und dann anschließend die Werte überschreiben:

C#-Code:
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.

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Th69 am 28.11.2018 09:55.

28.11.2018 09:54 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Demokrit
myCSharp.de-Mitglied

Dabei seit: 20.11.2018
Beiträge: 10

Themenstarter Thema begonnen von Demokrit

Demokrit ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von Th69:
Mittels  FileStream.Position kannst du auch gezielt zu einer Position in der Datei springen und dann anschließend die Werte überschreiben:

C#-Code:
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.

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:

C#-Code:
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();
        }
    }
}
28.11.2018 10:46 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Th69
myCSharp.de-Poweruser/ Experte

avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 3.388
Entwicklungsumgebung: Visual Studio 2015/17


Th69 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Wenn du aus der Datei lesen möchtest, dann mußt du selbstverständlich eine der Lese-Methoden aufrufen, z.B.  FileStream.ReadByte.
Mit

C#-Code:
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).
28.11.2018 10:57 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Demokrit
myCSharp.de-Mitglied

Dabei seit: 20.11.2018
Beiträge: 10

Themenstarter Thema begonnen von Demokrit

Demokrit ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von Th69:
Wenn du aus der Datei lesen möchtest, dann mußt du selbstverständlich eine der Lese-Methoden aufrufen, z.B.  FileStream.ReadByte.

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
28.11.2018 11:05 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Th69
myCSharp.de-Poweruser/ Experte

avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 3.388
Entwicklungsumgebung: Visual Studio 2015/17


Th69 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Was paßt denn nicht, wenn du fileStream.ReadByte() aufrufst?
Du mußt es nur noch für die Ausgabe in einen char casten:

C#-Code:
int data = fileStream.ReadByte();

Console.Write((char)data);
28.11.2018 13:12 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Demokrit
myCSharp.de-Mitglied

Dabei seit: 20.11.2018
Beiträge: 10

Themenstarter Thema begonnen von Demokrit

Demokrit ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Vielen Dank hat geklappt.
Kannst du eventuell noch erklären warum man das (char) an der Stelle braucht ?
28.11.2018 14:35 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Th69
myCSharp.de-Poweruser/ Experte

avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 3.388
Entwicklungsumgebung: Visual Studio 2015/17


Th69 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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.

Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von Th69 am 28.11.2018 15:02.

28.11.2018 14:57 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
david.m
myCSharp.de-Mitglied

Dabei seit: 02.06.2013
Beiträge: 82


david.m ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von Th69:
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.
28.11.2018 16:54 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Th69
myCSharp.de-Poweruser/ Experte

avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 3.388
Entwicklungsumgebung: Visual Studio 2015/17


Th69 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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).

Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von Th69 am 28.11.2018 18:07.

28.11.2018 18:02 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
LaTino LaTino ist männlich
myCSharp.de-Poweruser/ Experte

avatar-4122.png


Dabei seit: 03.04.2006
Beiträge: 2.975
Entwicklungsumgebung: Rider / VS2019 / VS Code
Herkunft: Thüringen


LaTino ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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
29.11.2018 08:39 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Th69
myCSharp.de-Poweruser/ Experte

avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 3.388
Entwicklungsumgebung: Visual Studio 2015/17


Th69 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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:

Zitat von Demokrit:
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?
29.11.2018 09:03 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
LaTino LaTino ist männlich
myCSharp.de-Poweruser/ Experte

avatar-4122.png


Dabei seit: 03.04.2006
Beiträge: 2.975
Entwicklungsumgebung: Rider / VS2019 / VS Code
Herkunft: Thüringen


LaTino ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top



Zitat von Th69:
Es ist schon klar, daß man Unicode-Texte mittels  StreamReader 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.
29.11.2018 10:25 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Demokrit
myCSharp.de-Mitglied

Dabei seit: 20.11.2018
Beiträge: 10

Themenstarter Thema begonnen von Demokrit

Demokrit ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ja vielen dank für die Antworten Daumen hoch


mycsharp.de  Moderationshinweis von Abt (29.11.2018 14:13):

Bitte keine Full Quotes:  [Hinweis] Wie poste ich richtig?
 
29.11.2018 13:17 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 11 Monate.
Der letzte Beitrag ist älter als 11 Monate.
Antwort erstellen


© Copyright 2003-2019 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 13.11.2019 15:36