Laden...

In CSV nur Werte einer bestimmten Zeile auslesen

Letzter Beitrag vor 6 Jahren 12 Posts 4.550 Views
In CSV nur Werte einer bestimmten Zeile auslesen

Hallo,

habe eine Frage und bräuchte einen Tipp...

Ich habe eine *.csv Datei in der Verschiedene Einträge vorhanden sind. Aufbau sieht so aus:

Head1 Head2 Head 3

12345, 456, 1232,
...
.....
.......

Head5 Head6 Head7

8889, 8889, 56556,
...
.....
......

Ich möchte jetzt gerne nur die Zahlen vom "Head5" einlesen....

wie mach ich das am Besten?!
Ich lesen so lange mit dem StreamReader die Zeilen ein bis ich zum "Head5" komme und dann halt ab der nächsten Zeile bis zum Komma!? Oder liege ich falsch??

Hätte da jemand einen Schnipsel für mich!?

Grüße an Alle und Vielen Dank schon jetzt für Eure Mühe.....

Regex.

Hallo zusammen,

zur Vollständigkeit [Artikel] Regex-Tutorial und https://regex101.com/

Gruss

Coffeebean

Zum Thema CSV und RegEx kann man sich folgenden Beitrag durchlesen

StackExchange/Software Engeniering: Can the csv format be defined by a regex?

Ein Beispiel für Regex.Split: https://www.dotnetperls.com/regex-split-numbers
Für den konkreten Fall dann "first match" oder "non-greedy" als Stichwort

Goalkicker.com // DNC Magazine for .NET Developers // .NET Blogs zum Folgen
Software is like cathedrals: first we build them, then we pray 😉

Okay, habe mir mal das regex angeschaut. So wie ich das sehe überprüfen ich damit nur, ob ich schon am Head5 angekommen bin und lese dann die Zahlen ein!?

Ist der Aufbau der "CSV"-Datei tatsächlich wie von dir geschildert? Falls ja, verwendest du einen eher merkwürdigen Aufbau. Reguläre stehen Überschriften / Bezeichner ja eher in der ersten Statts in der 15. Zeile.

Ansonsten: Du liest die Datei Zeilenweise ein und prüfst bei jeder Zeile ob du nun bei Head5 angekommen bist. Ist das der Fall, liest du ab der nächsten Zeile immer die Werte vor dem ersten Komma ein.

Oder habe ich etwas falsch verstanden?

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

ja, so solls sein und das scheinbar mit regex. Oder hast du einen anderen ansatz?

Hast Du eine Beispiel-Datei?
Ist denke ich besser, nur damit wir auch wirklich von dem gleichen Format ausgehen.

Wenn wenn es valides CSV ist, tuts auch eine Library wie der CsvHelper

Wenn Du mehrere Header-Zeilen auch zwischen den Daten hast, dann würde ich in folgenden Schritten vorgehen:

Jede Zeile nach Header-Zeilen prüfen. Ein Contains auf "Header5" könnte da schon reichen, wenn Du sicher sein kannst, dass das sonst nirgendwo steht.
Auf die gefundene Header-Zeile ein Split auf das Trennzeichen (Leerzeichen?) und anschließend heraus finden, an welcher Stelle im Array sich "Header5" befindet.
Ab dieser Zeile abwärz muss nun jede Zeile mit dem Trennzeichen (Komma?) gesplittet werden. In dem Array rufst Du nun den Wert ab, der den selben index wie der zuvor gesuchte Header hat.
Die Zeilen liest Du dann so lange, bis Du wieder eine Header-Zeile hast. Das erkennst Du z.B. daran, dass bei einem Split auf ein Komma nur ein Item raus kommt.

Ich hoffe, Du verstehst, wie ich das meine.
So kommst Du mMn. recht einfach ohne Regex aus und kannst ein Format wie das Folgende lesen.

Header1 Header2 Header3
1,2,3
1,2,3
Header4 Header5 Header6
1,2,3,4
1,2,3,4
Header7 Header8 Header9 Header10
1,2,3,4,5
1,2,3,4,5

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

ja so hört sich das vernünftig an....jetzt noch eine Frage. Wenn ich mit StreamReader einlese, wie prüfe ich den darin dann die einzelnen wörter ab? Ich muss ja die Zeile einlesen und nach jedem Leerzeichen trennen, damit ich weiß das es sich um ein Wort handelt. Dann schreibe ich es in ein array und prüfe ob es das Wort Header5 ist....oder geht es eleganter?

Hallo,

ein Möglicher Ansatz wäre:


public class CSVReader
    {
        private List<string> rows = new List<string>();

        public void Initialize(string csvPath)
        {
            // Prüfen ob Date existiert
            if (File.Exists(csvPath))
            {
                using (FileStream stream = File.OpenRead(csvPath))
                {
                    string currentLine = string.Empty;
                    // Datei Zeilenweise einlesen
                    using (TextReader reader = new StreamReader(stream))
                    {
                        while((currentLine = reader.ReadLine()) != null)
                            this.rows.Add(currentLine);
                    }
                }
            }
        }

        public IEnumerable<Int32> GetValues(string column)
        {
            int columnIndex = -1;
            bool beginRead = false;
            // Zeilen durchgehen und Werte suchen
            foreach (string row in rows)
            {
                // Spalten splitten
                string[] values = row.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                // alle spalten durchgehen und prüfen ob der Wert dem Header entspricht
                // wenn ja Spaltenindex nehmen und fortfahren
                if (columnIndex < 0)
                {
                    for (int i = 0; i < values.Length; i++)
                    {
                        if (values[i].Equals(column))
                        {
                            columnIndex = i;
                            break;
                        }
                    }
                }

                // wenn das lesen der Werte begonnen wurde (das heißt, ein gültiger Spaltenindex da ist) werden die Werte gelesen
                if (columnIndex >= 0 && beginRead)
                {
                    Int32 number = -1;
                    // versuchen den Wert in eine Zahl umzuwandeln, wenn es fehlschlägt abbruch
                    if (!Int32.TryParse(values[columnIndex], out number))
                        break;

                    // zahl zurück liefern
                    yield return number;
                }
                // lesen noch nicht begonnen und gültiger Spaltenindex
                // dann lesen
                else if (columnIndex >= 0)
                    beginRead = true;
            }
        }
    }

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

Super....Danke hat alles funktioniert. Habe jetzt eine Kombi aus Regex und dem Schnipsel von inflames2k genommen....

Danke...