Pour des raisons de codage qui vous feraient horreur (je suis trop gêné pour le dire), je dois stocker un certain nombre d'éléments de texte dans une seule chaîne.
Je vais les délimiter en utilisant un caractère.
Quel caractère est préférable d'utiliser pour cela, c'est-à-dire quel caractère est le moins susceptible d'apparaître dans le texte? Doit être imprimable et probablement inférieure à 128 en ASCII pour éviter les problèmes de paramètres régionaux.
En supposant pour une raison embarrassante que vous ne puissiez pas utiliser CSV, je dirais que vous allez avec les données. Prenez des exemples de données et effectuez un simple décompte de caractères pour chaque valeur 0-127. Choisissez l'un de ceux qui ne se produisent pas. S'il y a trop de choix, obtenez un plus grand ensemble de données. L'écriture ne prendra pas beaucoup de temps et vous obtiendrez la meilleure réponse pour vous.
La réponse sera différente pour différents domaines problématiques, donc | (pipe) est courant dans les scripts Shell, ^ est courant dans les formules mathématiques, et il en va probablement de même pour la plupart des autres caractères.
Personnellement, je pense que j'irais pour | (pipe) si vous avez le choix, mais utiliser des données réelles est le plus sûr.
Et quoi que vous fassiez, assurez-vous d'avoir élaboré un plan d'évasion!
Probablement | ou ^ ou ~ vous pouvez également combiner deux caractères
Je choisirais "Unit Separator" ASCII code "US": ASCII 31 (0x1F)
Dans l'ancien temps, la plupart des choses se faisaient en série, sans accès aléatoire. Cela signifiait que quelques codes de contrôle étaient intégrés dans ASCII.
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 est en ASCII, et il est pris en charge Unicode pour l'afficher (généralement un "nous" dans le même glyphe) mais de nombreuses polices ne l'affiche pas.
Si vous devez l'afficher, je recommanderais de l'afficher dans l'application, après l'avoir analysé en champs.
Lorsque vous utilisez différentes langues, ce symbole: ¬
s'est avéré être le meilleur. Cependant, je teste toujours.
Et si vous utilisiez un format de style CSV? Les caractères peuvent être échappés dans un format CSV standard, et il y a déjà beaucoup d'analyseurs déjà écrits.
Vous avez dit "imprimable", mais cela peut inclure des caractères tels qu'un onglet (0x09) ou un flux de formulaire (0x0c). Je choisis presque toujours des onglets plutôt que des virgules pour les fichiers délimités, car des virgules peuvent parfois apparaître dans le texte.
(Assez intéressant, le tableau ascii a les caractères GS (0x1D), RS (0x1E) et US (0x1F) pour les séparateurs de groupe, d'enregistrement et d'unité, quels qu'ils soient/étaient.)
Si par "imprimable" vous voulez dire un caractère qu'un utilisateur pourrait reconnaître et facilement taper, j'irais pour le tuyau | symbole en premier, avec quelques autres caractères étranges (@
ou ~
ou ^
ou \
, ou backtick que je n'arrive pas à saisir ici) comme une possibilité. Ces caractères +=!$%&*()-'":;<>,.?/
semblent être plus susceptibles de se produire dans la saisie utilisateur. Quant au trait de soulignement _
Et au hachage #
Et aux crochets {}[]
Je ne sais pas.
Pouvez-vous utiliser un symbole de tuyau? Il s'agit généralement du deuxième délimiteur le plus courant après les chaînes séparées par des virgules ou des tabulations. Il est peu probable que la plupart du texte contienne un tube, et ord ('|') renvoie 124 pour moi, ce qui semble correspondre à vos besoins.
Pour échapper rapidement, j'utilise des trucs comme celui-ci: disons que vous voulez concaténer str1, str2 et str3 ce que je fais est:
delimitedStr=str1.Replace("@","@a").Replace("|","@p")+"|"+str2.Replace("@","@a").Replace("|","@p")+"|"+str3.Replace("@","@a").Replace("|","@p");
puis pour récupérer l'usage d'origine:
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","@");
note: l'ordre de remplacement est important
son incassable et facile à mettre en œuvre
Cela peut être bon ou mauvais (généralement mauvais) selon la situation et la langue, mais gardez à l'esprit que vous pouvez toujours coder Base64 le tout. Vous n'avez alors pas à vous soucier d'échapper et d'échapper à différents modèles de chaque côté, et vous pouvez simplement séparer et diviser les chaînes en fonction d'un caractère qui n'est pas utilisé dans votre jeu de caractères Base64.
J'ai dû recourir à cette solution face à la mise en place de documents XML dans des propriétés/nœuds XML. Les propriétés ne peuvent pas contenir de blocs CDATA, et les nœuds échappés car CDATA ne peuvent évidemment pas contenir d'autres blocs CDATA sans casser la structure.
Le CSV est probablement une meilleure idée pour la plupart des situations.
Nous utilisons ascii 0x7f, qui est pseudo-imprimable et ne revient presque jamais en utilisation régulière.
Pipe pour la victoire! |
Vous devrez probablement choisir quelque chose et ignorer ses autres utilisations.
+
pourrait être un bon candidat.
Eh bien, cela dépendra de la nature de votre texte dans une certaine mesure, mais une barre verticale 0x7C n'apparaît pas très souvent dans le texte.
Je ne sais pas si vous devez utiliser ASCII, mais si vous pouvez l'encoder en UTF-8, vous pouvez trouver un symbole vraiment obscur comme: ╡
(U + 2561) - que j'utilise beaucoup dans mes programmes.
Vous pouvez également examiner la sérialisation des objets et créer simplement de nouveaux champs pour tous les éléments dont vous pourriez avoir besoin.
La pipe et le caret sont les choix évidents. Je noterais que si les utilisateurs sont censés taper la réponse entière, le curseur est plus facile à trouver sur n'importe quel clavier que le pipe.
Je ne pense pas avoir jamais vu une esperluette suivie d'une virgule en texte naturel, mais vous pouvez d'abord vérifier le fichier pour voir s'il contient le délimiteur, et si oui, utilisez une alternative. Si vous voulez toujours être en mesure de savoir que le délimiteur que vous utilisez ne causera pas de conflit, effectuez une boucle en vérifiant le fichier pour le délimiteur souhaité, et s'il existe, doublez la chaîne jusqu'à ce que le fichier ne corresponde plus. . Peu importe s'il existe des chaînes similaires, car votre programme ne recherchera que des correspondances de délimiteur exactes.