PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Java & regex



nul
22-06-2006, 12:37
Ich versuche gerade einen Xml-substring auf seine vollstaendigkeit zu pruefen.
Der grund ist, dass ich von einem Stream lese der mir immer nur teilstuecke liefert.
Dazu verwende ich einen StringBuffer um den XML-String zusammenzusetzen.

Regex war noch nie wirklich meine Staerke, und deshalb bitte ich euch um eure Hilfe!
Mein Momentaner stand ist folgender:


public class RegexTest {
public static void main(String[] args) {
// String regex = "<MSG(>|\\sID=\"\\d\">)[\\p{ASCII}[^(</MSG>)]]+";
// String regex = "<MSG(>|\\sID=\"\\d\">)[\\p{ASCII}&&[^</MSG>]]*";
// String regex = "[<MSG(>|\\sID=\"\\d\">)]{1}[\\p{ASCII}]+</MSG>";
String regex = "<MSG>|<MSG\\sID=\"\\d\">[\\p{ASCII}]*</MSG>";
String message = "d><MSG><MSG ID=\"2\"><INFO><TYPE> 6 </TYPE></INFO></MSG><MSG ID=\"1\"><INFO><TYPE>7</TYPE></INFO></MSG></MSG>";

System.out.println( "Regex: " + regex );
System.out.println( message + "\nmessage end\n" );

Pattern pattern = Pattern.compile( regex );
Matcher matcher = pattern.matcher( message );

while ( matcher.find() ) {
String m = matcher.group();
System.out.println( m );
}
}
}

Nun ist die Ausgabe aber folgende:

<MSG>
<MSG ID="2"><INFO><TYPE> 6 </TYPE></INFO></MSG><MSG ID="1"><INFO><TYPE>7</TYPE></INFO></MSG></MSG>

und nicht

<MSG ID="2"><INFO><TYPE> 6 </TYPE></INFO></MSG>
<MSG ID="1"><INFO><TYPE>7</TYPE></INFO></MSG>
Ich hoffe mir kann dabei einer Helfen! Ich werde zwar weiter probieren, bin aber sicher ihr seit 100mal schneller als ich!

mfg
nul

bischi
22-06-2006, 19:10
Hab ich das richtig verstanden: Du liest den String stückchenweise von irgend einer unsicheren Quelle ein und willst prüfen, ob du auch den ganzen hast? Ich würd vorher und nachher nen Hash-Code drüberlaufen lassen und den vergleichen - dürfte massiv schneller und zuverlässiger sein.

MfG Bischi

nul
22-06-2006, 19:20
Hash-Code? Wie soll das gehn? Quellen sind zum beispiel Devices vom Betriebssystem, ne andere ist eine Netzwerkverbindung ...
Der Text zwischen <MSG ID="X">...</MSG> kann ist variabl sein, auf den hab ich keinen Einfluss ...

bischi
22-06-2006, 19:21
Dann musst du mir nochmals erklären, was genau du machen willst; Einfach nur prüfen, ob sämtliche Tags wieder geschlossen sind?

MfG Bischi

nul
22-06-2006, 19:32
so in etwa, aber der starttag muss <MSG="ID"> und der schlusstag </MSG> sein!

bischi
22-06-2006, 19:34
so in etwa, aber der starttag muss <MSG="ID"> und der schlusstag </MSG> sein!
Und dafür brauchst du nen regex? Das sollte doch einfachst mittels Rekursion zu machen sein (so etwa 10 Zeilen Code - ohne Garantie :D )

MfG Bischi

nul
22-06-2006, 19:36
Ich denke regex ist aber dabei schneller - warum ich jetzt hier von Geschwindigkeit rede ist dir erst klar wenn ich dir erzaehle zuwas das alles sein soll ...

bischi
22-06-2006, 19:42
Ich denke regex ist aber dabei schneller
glaub ich nicht... wär aber einen Versuch wert...


- warum ich jetzt hier von Geschwindigkeit rede ist dir erst klar wenn ich dir erzaehle zuwas das alles sein soll ...
Na dann los ;)

MfG Bischi

PS: Erstellst du die XML-Tags eigentlich selbst? Oder bekommst du den String schon fixfertig? Falls ja, wär ein Hash-Code zumindest für die Netzwerkvariante wohl das schnellste (ist übrigens in TCP/IP so gemacht...).

Waxolunist
22-06-2006, 20:14
Wie wärs wenn dus richtig mit einem XML-Validator machst und einem Schema, mit dem MSG-Tag als mandatory und dazwischen alles andere?

Die gibts fixfertig, sind auf Geschwindigkeit hin optimiert und überprüfen all das, was du brauchst.

Ansonsten herumprobieren. Das führt mit Regex am schnellsten zum Erfolg.

nul
22-06-2006, 20:40
Ok, dann mal los ...
Ihr kennt doch sicher Echtzeit-Betriebssysteme, oder? Um es einfach zu sagen, ich muss fuer eine Erweiterung einer Erweiterung ein Programm zur Visualisierung und Steuerung schreiben.

Auf den XML-String habe ich so gut wie keinen Einfluss - und um genau zu sein, ist das nicht mal ein gueltiger xml-stream den ich empfange. Es sind nur die Teile die ich filtere gueltig. Deshalb kann ich auch erst nachdem ich die Nachricht gefiltert habe an einen XML-Parser (Sax oder Dom, was auch immer) denken!

Grundsaetzlich braeuchte ich ja nur einen Ausdruck in Java Regex der mir eine Zeichenkette (</MSG> negiert und nicht die einzelnen zeichen ([^</MSG>]).

P.S.: Fuer das "Java-Echtzeit-Programm" (wer erkennt an dem Wort noch den Witz?) verwende ich dabei nicht TCP/IP - wegen der Verzoegerung. TCP muss doch immer die Pakete quittieren, und das dauert halt laenger als bei UDP - na ihr wisst schon ...

mwanaheri
22-06-2006, 21:39
Wenn die Zeichenkette mit </MSG> enden muss, kannst du das doch einfach mit String.substr(String.length - 6,5).equals("</MSG>") prüfen. Analog auch den Anfang. Alles, was dem nicht entspricht, fliegt raus.
Den Rest würde ich entweder mit split("<") aufteilen und dann auf finales > prüfen oder durch einen StringTokenizer jagen. Das prüft natürlich nur die Klammern und ist nicht wirklich eine Gültigkeitsprüfung.

Diese Klassen brauchen zwar Speicher, ich finde sie aber recht flott. Das ganze ist sehr wartbar. RegEx sind zwar supermächtig, aber ich bin mir nicht sicher, ob sie wirklich schneller sind. Mächtigkeit hat auch seine Anforderungen.

nul
22-06-2006, 22:59
Hab jetzt mal ne Mischung aus Regex StringTokenizer StringBuffer und XML Parser verwendet - fuer den Moment bin ich damit zufrieden.
Wenn mir das dann mal zu langsam ist kann ich das ja immer noch spaeter aendern!

Danke an alle fuer eure Hilfe!!!

mwanaheri
23-06-2006, 10:17
Nachtrag: Wenn du nicht multithreaden musst und du Java 5 verwenden kannst, ist laut Doku der Stringbuilder (Aufrufgleich mit StringBuffer) performanter als der StringBuffer.

nul
23-06-2006, 11:51
Verwende schon Java 5, aber Threads muessen sein. Theoretisch koennte ich auch mit Signalen arbeiten - aber damit habe ich sehr schlechte erfahrungen gemacht. Ich weiss gar nicht wie oft mir dabei die VM schon abgestuerzt ist.
Mindestens 5 Mal? Ich finde jedenfalls im Projekt noch 5 Crash-Logs davon - wobei ich sicher welche schon geloecht habe!
Ausserdem haette das den Nachteil dass ich zum Beispiel fuer die Netzwerkverbindung wieder was anderes erfinden muesste.

Wenn ichs so mache wie es geplant ist dann kann ich fuer alle geplanten Verbindungsarten die gleiche Implementierung verwenden, ich muss nur dem Thread den richtigen Stream uebergeben.

bischi
23-06-2006, 16:37
Ok, dann mal los ...
Ihr kennt doch sicher Echtzeit-Betriebssysteme, oder? Um es einfach zu sagen, ich muss fuer eine Erweiterung einer Erweiterung ein Programm zur Visualisierung und Steuerung schreiben.
Echtzeitbetriebssysteme sind doch immer wieder toll...

Fuer das "Java-Echtzeit-Programm" (wer erkennt an dem Wort noch den Witz?)
:D

verwende ich dabei nicht TCP/IP - wegen der Verzoegerung. TCP muss doch immer die Pakete quittieren, und das dauert halt laenger als bei UDP - na ihr wisst schon ...
Ich würde mal behaupten, dass TCP/IP auf heutigen Systemen schneller ist, als UDP mit Java... (es muss ja nicht jedes mal das Paket bestätigt werden - die Netzwerkkarte hat ja glücklicherweise einen Buffer...). Und vor allem zuverlässiger... (afaik musst du ja beim Empfangen nicht warten - lediglich der Sender wartet auf die Antwort - und das kleine bisschen Checksumme dürfte doch Hardwaremässig gemacht werden...)

MfG Bischi