普通文本中最少使用的分隔符 < ASCII 128
Posted
技术标签:
【中文标题】普通文本中最少使用的分隔符 < ASCII 128【英文标题】:Least used delimiter character in normal text < ASCII 128 【发布时间】:2010-10-04 06:34:27 【问题描述】:出于让您感到恐惧的编码原因(我不好意思说),我需要将多个文本项存储在一个字符串中。
我会用一个字符来分隔它们。
哪个字符最适合用于此,即哪个字符最不可能出现在文本中?必须是可打印的,并且在 ASCII 中可能小于 128 以避免语言环境问题。
【问题讨论】:
请不要为难。您应该忽略所有说“哦,那是一种垃圾方式,而是这样做”的人。响应者不是要问为什么,而是要他们回答如何。我不在乎你为什么处于这个位置。我自己也参加过几次。祝你好运! 我遇到了同样的问题..在谷歌搜索或堆栈溢出之前我选择了 PIPE...因为我喜欢它的外观---|----就像一个瘦子。跨度> 这取决于文本的类型。某些类型的文本很少使用制表符,所以我经常使用它。但包括源代码在内的其他类型的文本经常使用它。你不能对你的源文本做一些统计吗?您不能在源文本中添加转义字符,从而使用您喜欢的任何内容作为分隔符吗? 不问也不尝试比不好意思问任何问题要糟糕得多。我来这里是为了回答同一个问题,我为自己有其他人与我分享同样的问题而感到自豪:) 对于那些可能在文本中包含|
的人,我实际上有这样一种情况,我需要将字符尽可能地减少到最少。由于大多数字段都包含有趣的文本,因此 CSV 由于转义过多而无法工作。我们的字段分隔符是/|
。斜线只是比较常见,但与你从未遇到过的管道配对。我一直在使用一个引擎,它每天都会通过它获取大量数据。这从未中断过,我也不需要封装单个字符串或转义特殊字符。平均而言,这种机制为我们节省了几个百分比的文本。
【参考方案1】:
我会选择“单位分隔符”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”),但许多字体不显示它。
如果您必须显示它,我建议在将其解析为字段后在应用程序中显示它。
【讨论】:
哇,谢谢。这正是我要寻找的。span> 【参考方案2】:假设由于某些令人尴尬的原因您不能使用 CSV,我想说的是数据。取一些样本数据,并为每个值 0-127 进行简单的字符计数。选择一个不会发生的。如果选择太多,请获取更大的数据集。写起来不会花太多时间,你会得到最适合你的答案。
对于不同的问题领域,答案会有所不同,所以 | (pipe) 在 shell 脚本中很常见, ^ 在数学公式中很常见,对于大多数其他字符来说可能也是如此。
我个人认为我会选择 | (管道)如果可以选择但使用真实数据是最安全的。
无论你做什么,确保你已经制定了一个逃生计划!
【讨论】:
我不会在这里嘲笑。在 magento 2 产品导出中,它们将许多属性合并到名为additional_attributes
的单个 csv 列中。
为什么不直接用四个空格替换文本中的所有制表符,并使用制表符\t
作为分隔符?
使用 CSV 以外的其他东西有很好的理由:由于引用字段,CSV 文件不容易与 cut 和 awk 等 unix 工具兼容。不会出现在其他地方并且可以输入的单个字符很容易成为首选。认识到这一点并不“尴尬”。【参考方案3】:
当使用不同的语言时,这个符号:¬
证明是最好的。不过我还在测试中。
【讨论】:
我喜欢这个想法,但我很好奇你是否能够归档包含像“Billy”¬“Car”¬“Red”¬“Garage”¬“3”这样的字符串并使用 cut . (即 $cut -d"¬" -f1 myfile.delim) 我把这个问题添加到这里:***.com/questions/19821639/… charcode 172 的not sign
不是ascii,而是cp-1252【参考方案4】:
大概 |或 ^ 或 ~ 你也可以组合两个字符
【讨论】:
重复使用两次可以防止任何误解。喜欢 ||或##【参考方案5】:您说的是“可打印”,但其中可能包含制表符 (0x09) 或换页 (0x0c) 等字符。我几乎总是为分隔文件选择制表符而不是逗号,因为逗号有时会出现在文本中。
(有趣的是,ascii table 包含字符 GS (0x1D)、RS (0x1E) 和 US (0x1F) 用于组、记录和单位分隔符,无论它们是/曾经是什么。)
如果“可打印”是指用户可以识别并轻松输入的字符,我会选择管道 |首先是符号,还有一些其他奇怪的字符(@
或 ~
或 ^
或 \
,或我似乎无法在此处输入的反引号)作为一种可能性。这些字符+=!$%&*()-'":;<>,.?/
似乎更有可能出现在用户输入中。至于下划线_
和哈希#
和括号[]
我不知道。
【讨论】:
标准 ASCII 码表确实包括四个专门为此目的设计的控制码,正如上面 Jason S 所提到的。它们是:28 FS
文件分隔符、29 GS
组分隔符、30 RS
记录分隔符、31 US
单元分隔符。不幸的是,几乎没有人使用它们,尽管这正是它们的用途。就我个人而言,我讨厌 CSV 格式的文件,因为如果我们想要支持他们的文件格式,那么很多人都没有仔细考虑并弄得我们程序员必须处理的混乱。
@deegee 这可能是这里最好的答案。除非数据包含二进制或非标准 ascii/unicode,否则这将始终适用于任何语言。你应该把它变成一个常规的答案。
@rahul 您是否有权将此标记为已接受的答案?在处理充满垃圾的用户输入数据时最有用。其他人注意:ALT+31 在 Windows 中获取 US (0x1F)。【参考方案6】:
如何使用 CSV 样式格式?字符可以以标准的 CSV 格式进行转义,并且已经编写了很多解析器。
【讨论】:
我比我的想法更喜欢这个。 +1。 我认为逗号是普通文本中的常用字符。如果它像使用 CSV 一样简单,我怀疑是否有必要提出这个问题...... csv 处理普通文本中的逗号以及其他一些问题。因此,文本中是否有逗号并不重要。 IIRC 它将文本放在引号中并转义引号。 @Jeremy:完全正确。这是一篇提到转义方案如何工作的***文章:en.wikipedia.org/wiki/Comma-separated_values 坦率地说:CVS 将处理所有您没有想到的问题,并确保您不必每两周修复一次“解决方案”,因为它会因以下原因而中断一些不可预见的输入。【参考方案7】:你可以使用管道符号吗?这通常是逗号或制表符分隔字符串之后最常见的分隔符。大多数文本不太可能包含管道,并且 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","@");
注意:替换的顺序很重要
它牢不可破且易于实施
【讨论】:
这确实是这里最好的答案,也是唯一正确的一个。这是唯一无法破解的答案。所有其他答案只会降低输入破坏格式的可能性,但这是一种非常非常糟糕的方法。选择的答案正确地谈到了使用这样的转义方案 - 但是一旦你这样做,分隔符的选择基本上是无关紧要的。 分隔符并不是完全不相关的。如果您选择一个常用字符——比如空格或字母“e”——你的转义字符串确实会变得很长,并且难以阅读。最好选择一个不常见的字符,这就是为什么我仍然更喜欢这种东西的管道符号。【参考方案9】:我们使用 ascii 0x7f,它是伪可打印的,几乎不会在常规使用中出现。
【讨论】:
为什么不选这个,这明明是最好的答案【参考方案10】:为胜利而战! |
【讨论】:
【参考方案11】:嗯,这在某种程度上取决于文本的性质,但垂直条 0x7C 不会经常出现在文本中。
【讨论】:
【参考方案12】:我认为我从来没有在自然文本中看到一个 & 后跟一个逗号,但是您可以先检查文件以查看它是否包含分隔符,如果是,请使用其他选项。如果您希望始终能够知道您使用的分隔符不会导致冲突,则执行循环检查文件以查找您想要的分隔符,如果存在,则将字符串加倍,直到文件不再有匹配项.是否有相似的字符串无关紧要,因为您的程序只会查找完全匹配的分隔符。
【讨论】:
【参考方案13】:根据情况和语言,这可能是好是坏(通常是坏的),但请记住,您始终可以对整个事物进行 Base64 编码。然后,您不必担心在每一侧转义和取消转义各种模式,您可以根据 Base64 字符集中未使用的字符简单地分离和拆分字符串。
在将 XML 文档放入 XML 属性/节点时,我不得不求助于这个解决方案。属性中根本不能有 CDATA 块,并且作为 CDATA 转义的节点显然不能在不破坏结构的情况下在其中有更多的 CDATA 块。
不过,对于大多数情况,CSV 可能是一个更好的主意。
【讨论】:
base64 编码是一个简单的解决方案,但是使用 CSV 的主要原因是因为您不必重新解析文本,使用 base64 还不如完全发明自己的格式。跨度> 【参考方案14】:竖线和插入符号都是显而易见的选择。我会注意到,如果希望用户键入整个响应,则插入符号在任何键盘上都比管道更容易找到。
【讨论】:
【参考方案15】:我以前使用过双管道和双插入符号。如果您不手动创建或修改文件,则不可打印字符的想法有效。使用快速随机访问文件存储和检索字段宽度。您甚至不必阅读文件..您实际上是通过引用从文件中提取出来的。这就是数据库进行一些存储的方式。但它们也管理记录之间的空间等。并引入了最大数据元素宽度的问题。 (索引附加一个标头,用于定义每个元素的宽度及其原始数据类型。后来他们引入了重新映射字符的压缩。这允许文本文件在传输中获得大约 1/8 的大小.. win的变长char编码
【讨论】:
【参考方案16】:让它动态化:)
在文件头声明你的控制字符
例如
delimiter: ~
escape: \
wrapline: $
width: 19
hello world~this i$
s \\just\\ a sampl$
e text~$someVar$~h$
ere is some \~\~ma$
rkdown strikethrou$
gh\~\~ text
会给字符串hello world
this is \just\ a sample text
$someVar$
here is some ~~markdown strikethrough~~ text
我已经实现了类似的东西:plaintar
文本容器格式,
在 ascii 中转义和包装 utf16 文本,
作为 mime 多部分消息的替代方法。
见https://github.com/milahu/live-diff-html-editor
【讨论】:
以上是关于普通文本中最少使用的分隔符 < ASCII 128的主要内容,如果未能解决你的问题,请参考以下文章