普通文本中使用最少的定界符<ASCII 128


79

出于编码方面的原因,这会使您感到恐惧(我不好意思地说),我需要将多个文本项存储在单个字符串中。

我将使用字符来分隔它们。

哪个字符最适合用于此目的,即哪个字符最不可能出现在文本中?必须可打印,并且以ASCII表示可能小于128,以避免区域设置问题。


44
请不要为难。您应该忽略所有说“哦,这是胡扯的方法,请改为这样做”的人。响应者不是在问为什么,而是在回答如何。我不在乎你为什么要担任这个职位。我自己也来过几次。祝好运!
伊恩·霍尔德

1
我也遇到了同样的问题..我在谷歌搜索或堆栈溢出之前选择了PIPE ...因为我喜欢它的外观--- | ----就像一个瘦人。

1
这取决于文本的类型。某些文本很少使用制表符,因此我经常这样做。但是其他类型的文本(包括源代码)也经常使用它。您无法对源文本进行一些统计吗?您不能在源文本中添加转义字符,从而使用任何您喜欢的分隔符吗?
hippietrail

不问与不尝试比尴尬问任何类型的问题要糟得多。我在这里回答相同的问题,我为自己感到骄傲,因为我还有其他一些人在与我分享相同的问题:)
Teoman shipahi 2013年

对于那些可能|在文本中带有的人,我实际上遇到了这样一种情况,我需要将字符尽可能地减少到最小。由于大多数字段中包含带有有趣文本的字符串,因此由于大量转义,CSV无法正常工作。我们的字段定界符为/|。斜线仅在中等水平出现,但与从未遇到过的管道配对。我一直在使用引擎,每天都会通过它传递大量数据。这从未中断过,我也不需要封装单个字符串或转义特殊字符。平均而言,该机制为我们节省了一些百分比的文本。
RLH 2013年

Answers:


33

假设出于某些令人尴尬的原因,您不能使用CSV,我想说一下数据。取一些样本数据,并对每个值0-127进行简单的字符计数。选择一种不会发生的情况。如果选择过多,请获取更大的数据集。不需要花费很多时间来编写,而且您会得到最适合自己的答案。

对于不同的问题域,答案将有所不同,因此| (pipe)在shell脚本中很常见,^在数学公式中很常见,大多数其他字符也可能如此。

我个人认为我会去| (管道)(如果可以选择),但处理真实数据最安全。

无论您做什么,请确保已制定出逃避方案!


我不会在这里嘲笑。在magento 2产品导出中,它们将许多属性合并到名为的csv的单个列中additional_attributes
斯蒂芬

1
为什么不只用四个空格替换文本\t中的所有制表符,然后使用制表符作为分隔符?
Elie G.

34

我会选择“单位分隔符” ASCII代码“ US”:ASCII 31(0x1F)

在过去,过去,大多数事情都是连续进行的,没有随机访问权限。这意味着一些控制代码已嵌入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.

单位分隔符采用ASCII,并且支持Unicode显示(通常在同一字形中为“ us”),但许多字体均不显示。

如果必须显示它,我建议在将其解析为字段之后在应用程序中显示它。


哇谢谢你。这正是我要寻找的。
Theunis


17

当使用其他语言时,此符号:¬

被证明是最好的。但是我仍在测试。


1
我喜欢这个主意,但是我很好奇您是否能够归档包含诸如“比利”,“汽车”,“红色”,“车库”,“ 3”之类的字符串并使用剪切。(即$ cut -d“
blehman 2013年

我说这个问题堆放在这里:stackoverflow.com/questions/19821639/...
blehman

9
这不是ASCII。
nebuch

15

您说的是“可打印的”,但是可以包含诸如制表符(0x09)或换页(0x0c)之类的字符。对于分隔文件,我几乎总是选择制表符而不是逗号,因为逗号有时可以出现在文本中。

(有趣的是,ascii表具有用于组,记录和单位分隔符的字符GS(0x1D),RS(0x1E)和US(0x1F),无论它们是什么。

如果“可打印的”是指用户可以识别并轻松键入的字符,那么我将尽力而为。首先是符号,还有其他一些奇怪的字符(@或者,~或者,^或者\,或者反引号,我似乎无法在此处输入)。这些字符+=!$%&*()-'":;<>,.?/似乎更可能出现在用户输入中。至于下划线_和哈希#以及括号,{}[]我不知道。


14
正如上面的Jason S所提到的,标准ASCII码表确实包含四个专门为此目的设计的控制代码。它们是:28 FS文件分隔符,29 GS组分隔符,30 RS记录分隔符,31 US单位分隔符。不幸的是,几乎没有人使用它们,尽管这正是它们的初衷。我个人讨厌CSV格式的文件,因为太多的人没有考虑透彻,并且弄乱了我们的程序员必须支持的格式,如果我们想支持他们的文件格式。
deegee

3
@deegee这可能是这里的最佳答案。除非数据包含二进制或非标准的ascii / unicode,否则它将始终以任何语言运行。您应该将此变成常规答案。
dhj 2014年

@rahul您有权力将其标记为已接受的答案吗?在处理充满垃圾的用户输入数据时最有用。其他说明:ALT + 31在Windows中获得US(0x1F)。
golfalot19年

14

您如何使用CSV样式格式?可以使用标准CSV格式对字符进行转义,并且已经编写了很多解析器。


我喜欢这个比我的想法更好。+1。
伊恩·霍尔德

我认为逗号是普通文本中的普通字符。如果使用CSV一样简单,我会怀疑是否有必要提出问题……
Jay

csv处理普通文本中的逗号以及其他一些问题。因此,文本中是否已经有逗号都没关系。IIRC会将文本放在引号中,然后将引号转义。
杰里米·法兰西

@杰里米:完全正确。这是一篇维基百科文章,其中提到了转义方案的工作方式:en.wikipedia.org/wiki/Comma-separated_values
rmeador

1
坦率地说:CVS将处理所有您没有想到的问题,并确保您不必每两周就解决“解决方案”,因为由于某些意外输入而使解决方案中断。
2009年

9

可以使用管道符号吗?通常是逗号或制表符分隔的字符串之后的下一个最常见的分隔符。大多数文本不太可能包含管道,而ord('|')为我返回124,因此似乎符合您的要求。


8

为了快速转义,我使用如下代码:假设您要合并str1,str2和str3,我要做的是:

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

然后检索原始用途:

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","@");

注意:更换顺序很重要

它坚不可摧且易于实施


2
这确实是最好的答案,也是唯一正确的imo。这是唯一无法破解的答案。所有其他答案只会降低输入破坏格式的可能性,但这是一种非常非常差的方法。选定的答案正确地说明了使用这样的转义方案-但是一旦您完成,定界符的选择实际上是无关紧要的。
Alfie

分隔符不是很无关紧要。如果您选择一个常见字符-说一个空格或字母“ e”-您的转义字符串的确会变得很长,并且很难阅读。最好选择一个不常见的字符,这就是为什么我仍然更喜欢使用管道符号来处理这种事情。
fool4jesus


2

我们使用ascii 0x7f,它是可伪打印的,并且在常规用法中几乎不会出现。


2

取决于情况和语言,这可能是好是坏(通常是不好),但是请记住,您始终可以对Base64进行整体编码。这样,您就不必担心转义和取消转义各种模式,并且可以简单地根据Base64字符集中未使用的字符来分离和分割字符串。

面对将XML文档放入XML属性/节点时,我不得不诉诸此解决方案。属性根本不能在其中包含CDATA块,并且转义的节点因为CDATA显然不能在其中进一步破坏CDATA块而不破坏结构。

不过,对于大多数情况,CSV可能是一个更好的主意。


base64编码是一个简单的解决方案,但是使用CSV的主要原因是因为您不必重新解析文本,因此,使用base64可能也可以完全发明自己的格式。
轧辊

1

嗯,这在某种程度上取决于文本的性质,但是竖线0x7C并不经常出现在文本中。


1

我认为我从未见过&符号,后接自然文本逗号,但是您可以首先检查文件以查看其是否包含定界符,如果是,请使用替代方法。如果您始终希望知道使用的定界符不会引起冲突,请循环检查文件中所需的定界符,如果存在,则将字符串加倍,直到文件不再匹配为止。是否存在相似的字符串并不重要,因为您的程序只会查找精确的定界符匹配项。


1

管道和插入号都是显而易见的选择。我要指出,如果希望用户键入整个响应,则在任何键盘上都比管道更容易找到插入符号。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.