5个不稳定版本
0.3.1 | 2022年2月27日 |
---|---|
0.3.0 | 2022年2月27日 |
0.1.1 | 2022年2月27日 |
0.1.0 | 2022年2月26日 |
0.0.1 | 2022年2月24日 |
在解析器实现中排名2640
19KB
132 行
UDV
无歧义分隔值。类似于CSV,但一致、无歧义、可预测。
描述
使用前导分隔符和简单的字符转义,允许简单且无歧义地引入单元和记录,无歧义地声明头部,无歧义地连接文档,能够区分0字段和1个空字段,以及能够使用任意二进制数据。
这是编码无关的,但分隔符必须是单个码点。显然的规范表示是utf-8和二进制,但任何编码都是可能的。
EBNF如下,其中全部大写值各自是一个可配置的单码点分隔符
stream = {garbage}, { message, {garbage} }, ENDSTREAM;
garbage = (* - (MESSAGE | HEADER | ENDSTREAM) )
message = [header], MESSAGE, { record }, ENDMESSAGE;
header = HEADER, units;
record = RECORD, units;
units = { UNIT, unit };
unit = { (* - control) | (ESCAPE, *) };
control = ENDSTREAM | HEADER | MESSAGE | ENDMESSAGE | RECORD | UNIT | ESCAPE;
默认分隔符
HEADER = "#";
MESSAGE = ">";
ENDMESSAGE = "<";
RECORD = ? ASCII newline ?;
UNIT = ",";
ESCAPE = "\";
ENDSTREAM = "!";
大多数情况下,这是一个以前缀为导向的格式。两个例外是ENDMESSAGE和ENDSTREAM分隔符。ENDMESSAGE分隔符允许在不插入换行符的情况下编辑文本UDV消息文件,而不会引起问题(因为这种格式的目的是无歧义,文件末尾的换行符必须被视为最后一个单元的一部分,或者引入一个空记录)。ENDSTREAM分隔符允许UDV数据不依赖于预先知道长度或依赖于流中缓冲区的物理几何形状。这是明确的,要求任何UDV消息中的ENDSTREAM码点必须显式转义,允许任何UDV解析器在任意位置无修改地解析UDV流。这也可以用来在文件末尾嵌入UDV流,并将UDV偏移量放在ENDSTREAM之后,以便可以从尾部数据定位开始位置。
示例,使用默认分隔符
带有头部和两个记录的单个消息
#,id,name,value>
,1,taylor,developer
,2,namewith\,comma,valuewith\
newline<
没有头部和两个记录的单个消息
>
,1,taylor,developer
,2,namewith\,comma,valuewith\
newline<
带有头部但没有记录的单个消息
#,id,name,value><
带有头部和一个空记录的单个消息
#,id,name,value>
<
带有空单元的头部,以及所有空单元的记录
#,id,name,,value>
,,,,<
最短的有效消息
><
没有头部和一个具有一个空单元的记录的单个消息
>
,<
没有头部,一个记录有一个空单元,一个记录有零个空单元,一个记录有一个空单元,一个记录有两个空单元
>
,
,,<
将所有前面的示例连接为消息流,以ENDSTREAM字符分隔结束
这利用了任何数量的垃圾数据都可能出现在任何 MESSAGE、HEADER 或 ENDSTREAM 字符之前的事实,允许尾部换行不会引起问题。
#,id,name,value>
,1,taylor,developer
,2,namewith\,comma,valuewith\
newline<
>
,1,taylor,developer
,2,namewith\,comma,valuewith\
newline<
#,id,name,value><
#,id,name,value>
<
#,id,name,,value>
,,,,<
><
>
,<
>
,
,,<
!
最短的有效流
!
相对于 CSV 的优势
- 标题被明确分隔,因此永远不会对第一行是否构成标题产生猜测。
- 解析非常简单且明确。没有像 CSV 那样的问题,需要确定换行符是否属于值的一部分,或者值周围的引号是否属于值的一部分,或者如何在值内部转义逗号和引号。
- 可以区分没有记录的消息、没有单位的记录的消息以及有一个空单位的消息。
- 带有或没有标题的多个文档可以连接到同一个流中,并且可以无损失地解析。由于消息周围垃圾数据的规则,通常可以天真地连接消息文件,只要它们的结尾没有 ENDSTREAM。
- 结束流 ENDSTREAM 允许 UDV 流嵌入更多数据中,并且可以使用其起始码点指针无问题地解析。
- 在二进制编码中,甚至可以无问题地嵌入二进制数据。还可以使用以下规则使用 C0 控制代码将自描述的二进制消息流嵌入其中
HEADER = SOH;
MESSAGE = STX;
ENDMESSAGE = ETX;
RECORD = RS;
UNIT = US;
ESCAPE = ESC;
ENDSTREAM = EOT;
如果你有一个主要是字符串消息的流,这些规则可以帮助将其序列化到尽可能紧凑的流中,同时尽可能少地进行转义。还有一个 C0-utf8 模式,在保持有效的 utf-8 的同时完成这项工作。
缺点
- 为了使格式明确而做出的妥协可能会使其手读和手写变得有些笨拙,尤其是在管理许多消息的流时。
- 因为字符串不是长度前缀,解析字符串必须逐字符进行,并且转义序列可能会干扰无复制读取。与其他二进制格式相比,这是一个缺点,而不是 CSV 或其他面向文本的格式。
依赖关系
~1MB
~19K SLoC