Am wenigsten verwendetes Trennzeichen im normalen Text <ASCII 128

80

Aus Codierungsgründen, die Sie entsetzen würden (es ist mir zu peinlich zu sagen), muss ich eine Reihe von Textelementen in einer einzigen Zeichenfolge speichern.

Ich werde sie mit einem Zeichen abgrenzen.

Welches Zeichen ist dafür am besten geeignet, dh welches Zeichen erscheint am seltensten im Text? Muss druckbar sein und wahrscheinlich weniger als 128 in ASCII, um Probleme mit dem Gebietsschema zu vermeiden.

Rahul
quelle
44
Bitte schäme dich nicht. Sie sollten alle Leute ignorieren, die sagen "Oh, das ist ein Mist, mach das stattdessen". Es ist nicht Sache der Antwortenden, sich zu fragen, warum, sondern wie. Es ist mir egal, warum du in dieser Position bist. Ich war selbst in ein paar. Viel Glück!
Iain Holder
1
Ich hatte das gleiche Problem ... und ich ging mit PIPE, bevor ich googelte oder überlief ... weil mir gefiel, wie es aussah --- | ---- wie eine Skinney-Person.
1
Das hängt von der Art des Textes ab. Einige Arten von Text verwenden selten Tabulatorzeichen, daher gehe ich oft damit um. Andere Arten von Text, einschließlich Quellcode, verwenden ihn jedoch häufig. Können Sie nicht einige Statistiken zu Ihrem Quelltext erstellen? Können Sie Ihrem Quelltext keine Escape-Zeichen hinzufügen und dabei alles verwenden, was Sie als Trennzeichen möchten?
Hippietrail
Nicht fragen und nicht versuchen ist viel schlimmer als sich zu schämen, irgendeine Art von Frage zu stellen. Ich bin hier, um die gleiche Frage zu beantworten, und ich bin stolz auf mich, dass ich einige andere Leute habe, die das gleiche Problem mit mir teilen :)
Teoman shipahi
Für diejenigen, die einen |in ihrem Text haben könnten , hatte ich tatsächlich einen solchen Fall, in dem ich die Zeichen so gering wie möglich halten musste. Da die meisten Felder Zeichenfolgen mit interessantem Text enthielten, funktionierte CSV nicht, da viel entkommen war. Unser Feldbegrenzer ist /|. Der Schrägstrich ist nur mäßig häufig, aber gepaart mit einem Rohr, auf das Sie nie stoßen. Ich habe eine Engine verwendet, durch die jeden Tag viele Daten übertragen werden. Dies ist nie kaputt gegangen, und ich musste nie eine einzelne Zeichenfolge einkapseln oder einem speziellen Zeichen entkommen. Im Durchschnitt haben wir durch diesen Mechanismus einige Prozent Text eingespart.
RLH

Antworten:

34

Angenommen, Sie können CSV aus irgendeinem peinlichen Grund nicht verwenden, würde ich sagen, gehen Sie mit den Daten. Nehmen Sie einige Beispieldaten und führen Sie für jeden Wert 0-127 eine einfache Zeichenanzahl durch. Wählen Sie eine der nicht vorkommenden. Wenn Sie zu viel Auswahl haben, erhalten Sie einen größeren Datensatz. Das Schreiben dauert nicht lange und Sie erhalten die beste Antwort für Sie.

Die Antwort ist für verschiedene Problembereiche unterschiedlich, also | (Pipe) ist in Shell-Skripten üblich, ^ ist in mathematischen Formeln üblich, und das gleiche gilt wahrscheinlich für die meisten anderen Zeichen.

Ich persönlich denke, ich würde mich für | entscheiden (Pipe) Wenn Sie die Wahl haben, aber mit echten Daten arbeiten, ist dies am sichersten.

Und was auch immer Sie tun, stellen Sie sicher, dass Sie ein Fluchtschema ausgearbeitet haben!

Nick Fortescue
quelle
Ich würde mich hier nicht lächerlich machen. Bei einem Magento 2-Produktexport werden mehrere Attribute in einer einzigen Spalte mit dem Namen csv zusammengeführt additional_attributes.
Stephen
1
Warum ersetzen Sie nicht einfach alle Tabulatorzeichen im Text durch vier Leerzeichen und verwenden ein Tabulatorzeichen \tals Trennzeichen?
Elie G.
35

Ich würde "Unit Separator" ASCII-Code "US" wählen: ASCII 31 (0x1F)

In den alten, alten Tagen wurden die meisten Dinge seriell ohne zufälligen Zugriff erledigt. Dies bedeutete, dass einige Steuercodes in ASCII eingebettet waren.

ASCII 28 (0x1C) File Separator - Used to indicate separation between files on a data input stream.
ASCII 29 (0x1D) Group Separator - Used to indicate separation between tables on a data input stream (called groups back then).
ASCII 30 (0x1E) Record Separator - Used to indicate separation between records within a table (within a group).  These roughly map to a tuple in modern nomenclature.
ASCII 31 (0x1F) Unit Separator - Used to indicate separation between units within a record.  The roughly map to fields in modern nomenclature.

Unit Separator ist in ASCII und es gibt Unicode-Unterstützung für die Anzeige (normalerweise ein "us" in derselben Glyphe), aber viele Schriftarten zeigen es nicht an.

Wenn Sie es anzeigen müssen, würde ich empfehlen, es in der Anwendung anzuzeigen, nachdem es in Felder analysiert wurde.

Edwin Buck
quelle
1
wow Danke. das war genau das, wonach ich gesucht habe.
Theunis
22

Wahrscheinlich | oder ^ oder ~ Sie können auch zwei Zeichen kombinieren

SQLMenace
quelle
10
Die Verwendung von doppelt so viel verhindert Missverständnisse. Wie || oder
##
17

Bei Verwendung verschiedener Sprachen gilt dieses Symbol: ¬

erwies sich als das Beste. Ich teste jedoch immer noch.

Ikarin
quelle
1
Ich mag diese Idee, aber ich bin neugierig, ob Sie in der Lage sind, Zeichenfolgen wie "Billy" - "Auto" - "Rot" - "Garage" - "3" zu archivieren und cut zu verwenden. (dh $ cut -d "¬" -f1 myfile.delim)
blehman
Ich habe diese Frage hinzugefügt, um sie hier zu stapeln: stackoverflow.com/questions/19821639/…
blehman
10
Dies ist kein ASCII.
nebuch
15

Sie sagten "druckbar", aber das kann Zeichen wie eine Registerkarte (0x09) oder einen Formular-Feed (0x0c) enthalten. Ich wähle für begrenzte Dateien fast immer Tabulatoren anstelle von Kommas, da Kommas manchmal im Text erscheinen können.

(Interessanterweise enthält die ASCII-Tabelle die Zeichen GS (0x1D), RS (0x1E) und US (0x1F) für Gruppen-, Datensatz- und Einheitentrennzeichen, unabhängig davon, welche diese sind / waren.)

Wenn mit "druckbar" ein Zeichen gemeint ist, das ein Benutzer erkennen und leicht eingeben kann, würde ich mich für die Pipe | entscheiden Symbol zuerst, mit ein paar anderen seltsamen Zeichen ( @oder ~oder ^oder \oder Backtick, die ich hier scheinbar nicht eingeben kann) als Möglichkeit. Diese Zeichen +=!$%&*()-'":;<>,.?/scheinen bei Benutzereingaben wahrscheinlicher vorzukommen. Was Unterstrich _und Hash #und die Klammern {}[]betrifft, weiß ich nicht.

Jason S.
quelle
14
Die Standard-ASCII-Codetabelle enthält vier Steuercodes, die speziell für diesen Zweck entwickelt wurden, wie oben von Jason S erwähnt. Dies sind: 28 FSDateitrenner, 29 GSGruppentrenner, 30 RSDatensatztrenner, 31 USEinheitentrenner. Leider benutzt sie so gut wie niemand, obwohl sie genau dafür gedacht sind. Persönlich verabscheue ich Dateien im CSV-Format, weil so viele Leute die Dinge nicht durchdenken und ein Chaos anrichten, mit dem wir Programmierer umgehen müssen, wenn wir ihre Dateiformate unterstützen wollen.
Deegee
3
@deegee das ist wahrscheinlich die beste Antwort hier. Sofern die Daten keinen binären oder nicht standardmäßigen ASCII / Unicode enthalten, funktioniert dies immer in jeder Sprache. Sie sollten dies in eine regelmäßige Antwort verwandeln.
Dhj
@rahul hast du die Befugnis, dies als akzeptierte Antwort zu markieren? Am nützlichsten beim Umgang mit Benutzereingabedaten voller Müll. Hinweis für andere: ALT + 31, um US (0x1F) in Windows abzurufen.
Golfalot
14

Wie wäre es mit einem CSV-Format? Zeichen können in einem Standard-CSV-Format maskiert werden, und es sind bereits viele Parser geschrieben.

Alex Fort
quelle
Das gefällt mir besser als meine Idee. +1.
Iain Holder
Ich denke, ein Komma zählt als normales Zeichen im normalen Text. Wenn es so einfach wäre wie die Verwendung von CSV, bezweifle ich, dass die Frage gestellt werden müsste ...
Jay
csv befasst sich mit Kommas im normalen Text sowie einigen anderen Themen. Es spielt also keine Rolle, dass der Text bereits ein Komma enthält. IIRC setzt Text in Anführungszeichen und entgeht Anführungszeichen.
Jeremy French
@ Jeremy: genau richtig. Hier ist ein Wikipedia-Artikel, in dem erwähnt wird, wie das
Escape-
1
Um es ganz klar auszudrücken: CVS wird sich mit all den Problemen befassen, an die Sie nicht gedacht haben, und sicherstellen, dass Sie Ihre "Lösung" nicht alle zwei Wochen reparieren müssen, da sie aufgrund unvorhergesehener Eingaben kaputt geht.
Aaron Digulla
9

Können Sie ein Rohrsymbol verwenden? Dies ist normalerweise das zweithäufigste Trennzeichen nach durch Kommas oder Tabulatoren getrennten Zeichenfolgen. Es ist unwahrscheinlich, dass der meiste Text eine Pipe enthält, und ord ('|') gibt für mich 124 zurück, sodass dies Ihren Anforderungen zu entsprechen scheint.

Jay
quelle
8

Für eine schnelle Flucht verwende ich solche Dinge: Angenommen, Sie möchten str1, str2 und str3 zusammenfassen. Ich mache Folgendes:

delimitedStr=str1.Replace("@","@a").Replace("|","@p")+"|"+str2.Replace("@","@a").Replace("|","@p")+"|"+str3.Replace("@","@a").Replace("|","@p");

dann, um die ursprüngliche Verwendung abzurufen:

splitStr=delimitedStr.Split("|".ToCharArray());
str1=splitStr[0].Replace("@p","|").Replace("@a","@");
str2=splitStr[1].Replace("@p","|").Replace("@a","@");
str3=splitStr[2].Replace("@p","|").Replace("@a","@");

Hinweis: Die Reihenfolge des Austauschs ist wichtig

Es ist unzerbrechlich und einfach zu implementieren

Mohammad Amin
quelle
2
Dies ist wirklich die beste Antwort hier und die einzig richtige imo. Es ist die einzige Antwort, die nicht gebrochen werden kann. Alle anderen Antworten verringern nur die Wahrscheinlichkeit, dass die Eingabe das Format verletzt, aber dies ist ein sehr, sehr schlechter Ansatz. Die ausgewählte Antwort spricht zu Recht von der Verwendung eines solchen Escape-Schemas - aber sobald Sie dies tun, ist die Wahl des Trennzeichens im Wesentlichen irrelevant.
Alfie
Trennzeichen ist nicht ganz irrelevant. Wenn Sie ein gemeinsames Zeichen auswählen - beispielsweise ein Leerzeichen oder den Buchstaben "e" -, wird Ihre maskierte Zeichenfolge in der Tat ziemlich lang und schwer zu lesen. Wählen Sie am besten einen ungewöhnlichen Charakter, weshalb ich für solche Dinge immer noch das Pfeifensymbol bevorzuge.
narr4jesus
2

Pfeife für den Sieg! |

Eppz
quelle
2

Wir verwenden ascii 0x7f, das pseudodruckbar ist und bei regelmäßiger Verwendung kaum auftaucht.

Joe
quelle
2

Dies kann je nach Situation und Sprache gut oder schlecht (normalerweise schlecht) sein. Beachten Sie jedoch, dass Sie das Ganze immer mit Base64 codieren können. Sie müssen sich dann nicht mehr darum kümmern, verschiedenen Mustern auf jeder Seite zu entkommen und sie zu entfernen, und Sie können Zeichenfolgen einfach anhand eines Zeichens trennen und teilen, das in Ihrem Base64-Zeichensatz nicht verwendet wird.

Ich musste auf diese Lösung zurückgreifen, wenn ich XML-Dokumente in XML-Eigenschaften / -Knoten einfügen wollte. Eigenschaften können überhaupt keine CDATA-Blöcke enthalten, und Knoten, die als CDATA maskiert wurden, können offensichtlich keine weiteren CDATA-Blöcke enthalten, ohne die Struktur zu beschädigen.

CSV ist jedoch wahrscheinlich für die meisten Situationen eine bessere Idee.

Coxy
quelle
Die base64-Codierung ist eine einfache Lösung. Der Hauptgrund für die Verwendung von CSV liegt jedoch darin, dass Sie den Text nicht erneut analysieren müssen. Mit base64 können Sie auch Ihr eigenes Format vollständig erfinden.
rollt
1

Nun, es wird in gewissem Maße von der Art Ihres Textes abhängen, aber ein vertikaler Balken 0x7C taucht nicht sehr oft im Text auf.

Jackson
quelle
1

Ich glaube nicht, dass ich jemals ein kaufmännisches Und gefolgt von einem Komma in natürlichem Text gesehen habe, aber Sie können die Datei zuerst überprüfen, um festzustellen, ob sie das Trennzeichen enthält, und wenn ja, eine Alternative verwenden. Wenn Sie immer wissen möchten, dass das von Ihnen verwendete Trennzeichen keinen Konflikt verursacht, führen Sie eine Schleife durch, in der die Datei auf das gewünschte Trennzeichen überprüft wird. Wenn es vorhanden ist, verdoppeln Sie die Zeichenfolge, bis die Datei keine Übereinstimmung mehr aufweist . Es spielt keine Rolle, ob es ähnliche Zeichenfolgen gibt, da Ihr Programm nur nach genauen Trennzeichenübereinstimmungen sucht.


quelle
1

Sowohl Pfeife als auch Caret sind die offensichtliche Wahl. Ich würde bemerken, dass, wenn von Benutzern erwartet wird, dass sie die gesamte Antwort eingeben, Caret auf jeder Tastatur leichter zu finden ist als Pipe.

Will Johnson
quelle