如何在C++及多语言中编码字符串,避免与分隔符':'冲突?
解决WaterBase键值含冒号的编码方案(无外部依赖、多语言友好)
针对你开发的WaterBase文本存储工具遇到的「键或值含冒号会被误判为分隔符」问题,下面提供两种无需外部依赖、且能轻松在多语言中实现的编码方案:
方案1:转义字符编码
核心思路是用转义符对冒号进行转义,存储时将内容中的特殊字符转换为安全格式,读取时再还原。
实现逻辑
- 存储阶段:
- 先将内容中的反斜杠
\转义为\\(避免后续转义冒号时冲突) - 再将内容中的冒号
:转义为\: - 最后按
type:key:value格式拼接存储
- 先将内容中的反斜杠
- 读取阶段:
- 遍历字符串,遇到反斜杠
\时,跳过当前字符,直接取下一个字符作为内容(不视为分隔符) - 遇到未转义的
:时,才作为字段分隔符处理
- 遍历字符串,遇到反斜杠
C语言示例片段
// 存储时的转义函数 void escape_char(char *dest, const char *src) { int i = 0, j = 0; while (src[i] != '\0') { if (src[i] == '\\') { dest[j++] = '\\'; dest[j++] = '\\'; } else if (src[i] == ':') { dest[j++] = '\\'; dest[j++] = ':'; } else { dest[j++] = src[i]; } i++; } dest[j] = '\0'; } // 读取时的反转义函数 void unescape_char(char *dest, const char *src) { int i = 0, j = 0; while (src[i] != '\0') { if (src[i] == '\\' && src[i+1] != '\0') { dest[j++] = src[i+1]; i++; } else { dest[j++] = src[i]; } i++; } dest[j] = '\0'; }
方案2:长度前缀编码
核心思路是给每个字段(type、key、value)添加长度前缀,通过长度来确定字段边界,完全规避分隔符冲突问题。
实现逻辑
- 存储阶段:
- 计算type、key、value的字符串长度
- 按
[长度]:[内容]的格式拼接所有字段,最终格式为:type_len:type:key_len:key:value_len:value - 例如:type为"int"(长度3),key为"user:id"(长度7),value为"123:456"(长度7),存储内容为
3:int:7:user:id:7:123:456
- 读取阶段:
- 从字符串开头读取到第一个
:,得到type的长度,然后读取对应长度的字符作为type - 接着读取下一个
:前的数字作为key长度,读取对应长度的字符作为key - 最后读取value长度和value内容,全程无需关注内容中的冒号
- 从字符串开头读取到第一个
C语言示例片段
// 存储时拼接长度前缀 void build_prefixed_string(char *dest, const char *type, const char *key, const char *value) { int t_len = strlen(type); int k_len = strlen(key); int v_len = strlen(value); sprintf(dest, "%d:%s:%d:%s:%d:%s", t_len, type, k_len, key, v_len, value); } // 读取时解析长度前缀 int parse_prefixed_string(const char *src, char *type, char *key, char *value) { char *ptr = (char*)src; // 解析type长度和内容 int t_len = atoi(ptr); ptr += strlen(ptr) + 1; // 跳过数字和冒号 strncpy(type, ptr, t_len); type[t_len] = '\0'; ptr += t_len + 1; // 解析key长度和内容 int k_len = atoi(ptr); ptr += strlen(ptr) + 1; strncpy(key, ptr, k_len); key[k_len] = '\0'; ptr += k_len + 1; // 解析value长度和内容 int v_len = atoi(ptr); ptr += strlen(ptr) + 1; strncpy(value, ptr, v_len); value[v_len] = '\0'; return 0; }
方案对比
| 方案 | 优点 | 缺点 |
|---|---|---|
| 转义字符编码 | 存储格式相对直观,易手动阅读 | 解析时需处理转义嵌套,逻辑稍复杂 |
| 长度前缀编码 | 解析逻辑简单高效,无转义冲突 | 存储格式可读性稍弱,多了长度字段 |
两种方案均无需依赖任何外部库,所有主流编程语言都具备字符串长度计算、截取、替换的基础API,非常适合多语言拓展场景。
内容的提问来源于stack exchange,提问作者coderGtm
相关产品推荐
相关产品推荐

