Hi und Hallo,
komme bei der Behandlung eines Split Befehls nicht weiter.
Ich lese folgenden String ein:
AT-GER#1#0151223#2010-01-02#555555555555555555555555555555554#527677882774#233233233233#No Statement!
Soweit so gut, dieser wird bei der # und bei einem Zeilenumbruch gesplittet. Funktioniert auch alles.
Jetzt hab ich allerdings das Problem, dass ich die Fehler einer mangelhaften Programmierung ausbügeln muss. Der 3. Wert "0151223" (nach der 2. #) ist ein Passwort welches der Benutzer, der diesen Datensatz erstellt, selber wählen kann. Viele werden jetzt schon das Problem kommen sehen...
Die Ersteller des Web-Fragebogens haben es irgendwie versäumt die # in diesem Feld zu verbieten und natürlich gibt es jetzt Benutzer die eine # in ihrem Passwort verwenden.
Das würde dann so aussehen:
AT-GER#1#0151#223#2010-01-02#555555555555555555555555555555554#527677882774#233233233233#No Statement!
Jetzt Splittet natürlich mein Programm 1 x zuviel und bringt somit alles durcheinander.
Die Frage: Hat jemand eine Idee wie ich diese Ausnahme im Passwort irgendwie abfangen kann? z.B. in dem ich die # Zeichen zähle die vorkommen bevor das erste mal mit dem Zeilenumbruch "\n" gesplittet wird?
Rein theoretisch könnte in dem Passwortfeld beliebig viele # Zeichen verwendet werden und sogar im letzten Feld "No Statement!" (Kommentarfeld) könnten # Zeichen vorkommen.
Es ist jetzt nicht wichtig diesen Datensatz zu korrigieren, ich müsste ihn nur irgendwie gesondert ausweisen (zur händischen Kontrolle z.B.), es müsste dafür aber der Gesamte Datensatz aus dem gesplitteten String rausgenommen werden.
Ich bin hierbei echt überfragt.
Jemand eine Idee? =)
lg DN
Hier bietet sich viel eher Regex an.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Zeichen verbieten ist unschön, lieber maskiert man es. Z.B. so wie man in einem String ein " durch " maskieren muss, was dann wieder zur Folge hat dass man den Backslash an sich auch maskiert (durch \).
Dann hast du es mit String.Split auch nicht so einfach, aber du hast wenigstens eine Möglichkeit um eindeutig zu erkennen ob # ein Trennzeichen oder ein gewünschtes Zeichen im String ist.
In deinem Fall mit nur genau einem solchen Wert kannst du dir ja noch recht einfach behelfen. Splitte den String und schau dir an wie viele Felder dabei rauskommen.
Wenns 10 sein sollten und 12 sinds tatsächlich, gehören 3 zum Passwort. Die setzt du wieder zusammen.
Dann würd ich schauen dass der Fragebogen gescheit programmiert wird.
Ich denke ich komme mit folgendem Code zum richtigen Ergebnis, vielleicht nicht ne sonderlich schöne Variante, aber es müsste gehen.
Werde noch den Tipp von Chilic beherzigen und versuchen die Datensätze selber zu korrigieren, das Problem ist ja leider, dass in 2 Spalten die # reingeschrieben werden kann und da die Zuordnung dann finden wird glaub ich nicht möglich sein
split1 = dData.Split(new Char[] { '\n' });
for(int n = 0; n <= split1.Count()-1; n++)
{
split = split1[n].Split(new Char[] { '#'});
foreach (string u in split)
{
count += 1;
}
if (count > 8)
{
falseList.Add(n);
count = 0;
}
count = 0;
}
die Werte die in die "falseList" geschrieben werden sind Datensätze die öfter als 8 mal gesplittet werden (pro Zeile) und somit ist irgendwo eine # zu viel.
Der Index dieser Zeile wird in die besagte falseList geschrieben und diese überprüfe ich anschließend beim einlesen meiner Daten in meine List of Lists und die werden in der anschließenden Excel Datei ganz unten mit etwas Abstand ausgegeben zur händischen Kontrolle.
Hoffe das funktioniert so ^^
Hallo DearNobody,
dein Code basiert darauf, dass man mit 100%iger Sicherheit erkennen kann, ob ein Datensatz als ganzes korrekt ist oder eben mindestens ein zusätzliches Trennzeichen enthält, es sich aber im allgemeinen - da es sich um mehr als ein betroffenes Freitextfeld handelt - nicht 100%iger sicher entscheiden lässt, wieviele der überzähligen Rautenzeichen sich in welchem der beiden Felder befinden. Das ist einfach so.
Besonders klar wird es, wenn man sich vorstellt, dass sich die beiden Textfelder direkt hintereinander befinden würden. Je mehr Felder unterschiedlichen Formats sich dazwischen befinden und je kürzer die maximale Textlänge der Freifelder ist, desto größer sind die Chancen, dass man sicher ermitteln kann, wo ein bestimmtes Feld zwischen den beiden Textfeldern beginnt und so wieder in den Tritt kommt.
Solange sich in jedem der (beiden Teil-)Abschnitte, von dem man auf diese Weise weiß, wo sie beginnen und wo sie enden, nur ein Feld befindet, das überschüssige Trennzeichen enthalten kann, kann man alle Feldergrenzen korrekt bestimmen, indem man jeweils die Trennzeichen von vorne und von hinten bis zu dem fraglichen Feld bestimmt und alle verbleibenden Trennzeichen sind dann automatisch Teil des Inhalts des fraglichen Feldes. Und der Teil lässt sich leicht programmieren.
Wenn es allerdings nur wenige Sätze gibt, die betroffen sind, ist es schon ganz richtig, diese einfach nur zu erkennen, auszusortieren und händisch nachbearbeiten zu lassen.
herbivore
Danke für die info. Ich hab mir das ganze so angeschaut und gesehen, dass das Datumsfeld ja fix 10 Stellen hat und das darauffolgende (mit den ganzen Zahlen) immer 33 Stellen hat, somit kann ich schonmal fix sagen ob in dem Passwortfeld 1 oder mehrere # drinnen sind.
Wenn er dann dieses Feld richtig ausgibt, dann muss das letzte Feld (Spalte 8) dann das letzte sein, wenn es also 9+ Strings in dem Array gibt, dann ist im KommentarFeld eine oder mehrere # zuviel.
Damit sollte ich eigentlich den kompletten Datensatz korrigieren können. Danke für die Hilfe!
Noch ne Frage, gibt es eine schönere Möglichkeit den Split zu verhindern als:
Ihn zulassen und anschließend wieder zusammenzubauen? also durchaus das Passwortfeld splitten lassen und dann bei der Überprüfung, sofern erforderlich, wieder zu einem String zusammen zu bauen?
Hallo DearNobody,
ja, mit dem schon genannten Regex geht das, siehe
[Artikel] Regex-Tutorial
On-the-fly Regex-Tester: Regex-Lab
Man schreiben einen passenden Pattern und kann dann die einzelnen Gruppen gezielt auslesen.
herbivore
Mit Regex geht das ganz einfach:
^([^#]+)#([^#]+)#(.+)#([0-9]{4}-[0-9]{2}-[0-9]{2})#([0-9]+)#([0-9]+)#([0-9]+)#(.*)$
Das würde die einzelnen Felder alle in Gruppen tun, wobei bei dem PW und dem letzten Feld # erlaubt sind.
Darth Maim
Danke vielmals für all die Hilfe, habs nun geschafft alle Datensätze zu korrigieren =).
Aber ich Post mal lieber nicht den Code, der sieht jetzt echt wild aus, habs nämlich noch ohne dem RegEx gemacht. (Werd den Code aber, wenn ich mal mehr Zeit habe, überarbeiten und RegEx verwenden). Danke nochmals =).
lg DN
Hallo DearNobody,
das liegt aber nicht unbedingt an dir, sondern bestätigt nur, war ich mit dieser Aufgabe im Das Programmier-Spiel: nette Übungsaufgaben für zwischendurch beweisen konnte: Wenn man einen Regex-Pattern in normalem Code ausprogrammiert wird es aufwändig, länglich und unübersichtlich.
Regex sollte man sich auf jeden Fall aneignen. Ich habe es glücklicherweise schon während des Studiums gelernt und profitiere nun schon mein ganzes Leben davon.
herbivore
Sry für Offtopic. Ja Regex sind ein echt mächtiges Werkzeug. Ich hab leider auch viel zu spät angefangen Sie zu nutzen.
Aber dazu fällt mir noch ein Jamie Zawinski Zitat ein:
Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.
Was leider auch häufig zutrifft.
Hallo chavez,
die zwei Probleme hat man allerdings nur dann, wenn man Regex auf ein Problem anwendet, das sich für Regex nicht eignet. Und so und nur so war das Zitat auch gemeint. Das Zitats war eine Antwort auf den eigentlich scherzhaft gemeinten Vorschlag, alle Arten von Daten als Byte-Strom zu betrachten und diesen dann mit Regex zu manipulieren (siehe Source of the famous “Now you have two problems” quote), was natürlich Unsinn ist. Wenn man Regex auf Probleme anwendet, für die es sich eignet, und da gibt es eine Menge, hat man nicht zwei Probleme, sondern eine gute und schnelle Lösung.
herbivore