90

由于编码原因会让您感到恐惧(我不好意思说),我需要将多个文本项存储在一个字符串中。

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

哪个字符最好用于此,即哪个字符最不可能出现在文本中?必须是可打印的,并且在 ASCII 中可能小于 128,以避免语言环境问题。

4

16 回答 16

51

我会选择“单位分隔符”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 支持来显示它(通常是同一字形中的“我们”),但许多字体不显示它。

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

于 2017-01-09T19:31:19.600 回答
37

假设由于某些令人尴尬的原因您不能使用 CSV,我会说使用数据。取一些样本数据,并为每个值 0-127 进行简单的字符计数。选择一个不会发生的。如果选择太多,请获取更大的数据集。不会花太多时间来写,你会得到最适合你的答案。

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

我个人认为我会去| (管道)如果可以选择但使用真实数据是最安全的。

不管你做什么,确保你已经制定了一个逃生计划!

于 2009-01-29T15:48:32.023 回答
23

使用不同语言时,此符号: ¬

被证明是最好的。不过我还在测试。

于 2010-09-01T16:49:34.990 回答
22

可能| 或 ^ 或 ~ 你也可以组合两个字符

于 2009-01-29T15:38:49.737 回答
17

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

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

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

于 2009-01-30T01:29:35.113 回答
14

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

于 2009-01-29T15:38:31.873 回答
9

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

于 2009-01-29T15:38:20.033 回答
9

为了快速转义,我使用这样的东西:假设你想连接 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","@");

注意:替换的顺序很重要

它牢不可破且易于实施

于 2011-08-13T07:58:20.427 回答
3

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

于 2009-01-30T01:09:42.687 回答
2

管为胜利!|

于 2009-01-29T15:41:43.177 回答
1

好吧,它在某种程度上取决于文本的性质,但垂直条 0x7C 不会经常出现在文本中。

于 2009-01-29T15:39:34.647 回答
1

我认为我从未见过自然文本中的 & 后跟逗号,但是您可以先检查文件以查看它是否包含分隔符,如果是,请使用替代方法。如果您希望始终能够知道您使用的分隔符不会导致冲突,那么请循环检查文件中是否存在您想要的分隔符,如果存在,则将字符串加倍,直到文件不再有匹配项. 是否有类似的字符串并不重要,因为您的程序只会查找完全匹配的分隔符。

于 2009-02-11T05:28:27.640 回答
1

根据情况和语言,这可能是好是坏(通常是坏的),但请记住,您始终可以对整个事物进行 Base64 编码。然后,您不必担心在每一侧转义和取消转义各种模式,您可以根据 Base64 字符集中未使用的字符简单地分离和拆分字符串。

面对将 XML 文档放入 XML 属性/节点时,我不得不求助于这个解决方案。属性中根本不能有 CDATA 块,并且作为 CDATA 转义的节点显然不能在不破坏结构的情况下在其中有更多的 CDATA 块。

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

于 2009-02-11T05:59:43.413 回答
1

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

于 2013-08-19T23:55:17.233 回答
0

我以前使用过双管和双插入符号。如果您不手动创建或修改文件,则不可打印字符的想法有效。使用快速随机访问文件存储和检索字段宽度。您甚至不必阅读文件..您实际上是通过引用从文件中提取的。这就是数据库进行一些存储的方式。但它们也管理记录之间的空间等。并引入了最大数据元素宽度的问题。(索引附加一个标头,用于定义每个元素的宽度及其原始数据类型。后来他们引入了重新映射字符的压缩。这允许文本文件在传输中获得大约 1/8 的大小.. win 的可变长度字符编码

于 2021-02-13T13:22:11.003 回答
0

让它充满活力:)

在文件头中宣布你的控制字符

例如

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

于 2021-05-10T06:21:15.593 回答