Calocybe: Trennzeichen zum Inhalte in Textdateien abzuspeichern

Beitrag lesen

Moin auch!

wollte euch mal fragen was eigentlich so die beste Methode ist, um mehrere Werte die in einer Textdatei abgespeichert werden zu trennen.

Wenn ich nicht mit absoluter Sicherheit das Vorkommen eines bestimmtes Zeichens in den zu speichernden Texten ausschliessen kann (und genau das ist ja Dein Problem), gehe ich gewoehnlich folgenden Weg:

* Auswaehlen eines schoenen griffigen Trennzeichens. | und ; sind gute Kandidaten, prinzipiell ist aber auch ein grosses A oder kleines m moeglich (wie Du gleich sehen wirst). Ich gehe im folgenden mal von | als Beispiel aus.

* Entwerfe ein Codierungsschema. Was sich da anbietet, ist vielleicht ein bisschen sprachabhaengig. Ich gehe jetzt mal von Perl aus, wo man eine eingelesene Zeile am besten mit split() in die Felder zerlegt. An dieser Stelle funktioniert eine einfache Maskierung mit \ *nicht*, weil split an einem | immer noch splitten wuerde, es sei denn, man schliesst einen \ vor dem | per regexp aus. Das geht zwar, aber die naechste Ausnahme folgt auf dem Fuss: Bei \| ist der zweite \ geschuetzt, das | stellt tatsaechlich einen Feldtrenner dar, sodass hier doch gesplittet werden soll. Man sieht leicht, dass man das ewig so fortsetzen kann.

Daher waehlt man eine Kodierung, die das zu kodierende Zeichen selbst nicht mehr enthaelt. Ich tendiere da zur Verwendung des hexadezimalen ASCII-Codes des Zeichens, nagefuehrt von einem Markierungszeichen. Das Markierungszeichen selbst muss dann (bzw. vorher) natuerlich auch codiert werden, sonst wuerde man beim spaeteren Decodieren ja an den falschen Stellen arbeiten, wenn im Text bereits dieses Zeichen vorkommt. Waehlen wir also von mir aus wieder den \ als Einleitungszeichen der Codierung, schreiben aber diesmal den hex ascii code des zu codierenden Zeichens dahinter. Der ist 5C fuer den Backslash selbst, und 7C fuer das Pipe-Zeichen.

Man codiert also: Zuerst(!!) den Backslash:
    s/\/\5C/g;
  dann das Pipe-Zeichen:
    s/|/\7C/g;
  (geht in Perl natuerlich auch schoener in einem Rutsch)

Hier jetzt die Felder mit | zusammenfuegen und in Datei schreiben.

Spaeter dann Datei auslesen und Felder am | splitten. Dann einzelne Felder decodieren, und zwar in genau der umgekehrten Reihenfolge wie bei der Codierung. Auf keinen Fall zuerst den Backslash decodieren, weil der ja dann im naechsten Durchlauf wieder eine Codierung an der falschen Stelle anzeigen wuerde. Aber in Perl kann man auch einfach
    s/\([0-9A-Fa-f]{2})/chr(hex($1))/eg;       # aus dem Kopf, ungetestet
  schreiben, das arbeitet von vorn nach hinten durch, sodass keine Doppel-Decodierung auftritt (hier zeigt sich, warum die Verwendung des ASCII-Codes Sinn macht).

Soweit zum Prinzip. Ich persoenlich benutze lieber folgende Variante:
  Codierung:
    s/([%|\x00-\x1F])/'%'.ord($1).';'/ge;       # codiert auch Steuerzeichen (incl. Zeilenumbrueche)
  Decodierung:
    s/%(\d+);/chr($1)/ge;
  Das hat keine zwingenden Gruende, sieht nur schoener aus und ist einfacher, als jedes Zeichen einzeln zu codieren.

Nicht beruecksichtigt wurden hier irgendwelche Zeichensatzprobleme (die Zeichencodes ueber 128 varriieren zwischen den Zeichensaetzen). Das macht aber nichts, solange Du nur beim Decodieren denselben Zeichensatz zurueckerwartest, den Du beim Codieren verwendet hast, was gewoehnlich der Fall ist.

HTH && So long

--
Scientists say there are over 3,000 spiders for every human being on earth. Does anybody want mine? I certainly don't.
    -- Chuck Bonner