protobuf之string bytes的区别

解析协议缓冲区时包含无效的UTF-8数据。如果您打算发送原始字节,请使用“bytes”类型问题 我确定至少在C++中,我们在解析过程中验证字符串是UTF-8,而不是在序列化过程中。因此,如果C++做了类似的事情,那么就有可能用非UTF-8字符串来序列化proto,这在稍后再次解析proto之前不会被检测到。如果您需要能够在该字段中存储非UTF-8数据,那么您可能需要考虑将其从字符串字段更改为字节字段,这通常是一种安全的更改。字符串字段仅用于存储UTF-8数据,因此如果您需要发送非UTF-8数据,那么最好使用。类型都对应与**C++**的std::string类型。关于第二点,两个函数都定义在** 阅读详情

protobuf提供了多种基础数据格式,包括string/bytes。从字面意义上,我们了解bytes适用于任意的二进制字节序列。然而对C++程序员来讲,std::string既能存储ASCII文本字符串,也能存储任意多个\0的二进制序列。那么区别在哪里呢?

同时在实际使用中,我们偶尔会看到类似这样的运行错误:

[libprotobuf ERROR google/protobuf/wire_format.cc:1091] String field 'str' contains invalid UTF-8 data when serializing a protocol buffer. Use the 'bytes' type if you intend to send raw bytes.

[libprotobuf ERROR google/protobuf/wire_format.cc:1091] String field 'str' contains invalid UTF-8 data when parsing a protocol buffer. Use the 'bytes' type if you intend to send raw bytes.

这篇文章从源码角度分析下string/bytes类型的区别。

在之前的文章里介绍过protobuf序列化的过程,我们看下string/bytes序列化的过程。 在之前的文章里介绍过protobuf序列化的过程,我们看下string/bytes序列化的过程。

所有的序列化操作都会在SerializeFieldWithCachedSizes这个函数里进行。根据不同的类型调用对应的序列化函数,例如对于string类型

case FieldDescriptor::TYPE_STRING: {

string scratch;

const string& value = field->is_repeated() ?

message_reflection->GetRepeatedStringReference(

message, field, j, &scratch) :

message_reflection->GetStringReference(message, field, &scratch);

VerifyUTF8StringNamedField(value.data(), value.length(), SERIALIZE,

field->name().c_str());

WireFormatLite::WriteString(field->number(), value, output);

break;

}

而对于bytes类型:

case FieldDescriptor::TYPE_BYTES: {

string scratch;

const string& value = field->is_repeated() ?

message_reflection->GetRepeatedStringReference(

message, field, j, &scratch) :

message_reflection->GetStringReference(message, field, &scratch);

WireFormatLite::WriteBytes(field->number(), value, output);

break;

}

可以看到在序列化时主要有两点区别:

  1. string类型调用了VerifyUTF8StringNamedField函数
  2. 序列化函数不同:WriteString vs WriteBytes

关于第二点,两个函数都定义在wire_format_lite.cc,实现是相同的。

那么我们继续看下第一点,VerifyUTF8StringNamedField调用了VerifyUTF8StringFallback(话说一直不理解fallback在这里什么意思,protobuf源码里经常看到这个后缀)。看下这个函数的实现:

void WireFormat::VerifyUTF8StringFallback(const char* data,

int size,

Operation op,

const char* field_name) {

if (!IsStructurallyValidUTF8(data, size)) {

const char* operation_str = NULL;

switch (op) {

case PARSE:

operation_str = "parsing";

break;

case SERIALIZE:

operation_str = "serializing";

break;

// no default case: have the compiler warn if a case is not covered.

}

string quoted_field_name = "";

if (field_name != NULL) {

quoted_field_name = StringPrintf(" '%s'", field_name);

}

// no space below to avoid double space when the field name is missing.

GOOGLE_LOG(ERROR) << "String field" << quoted_field_name << " contains invalid "

<< "UTF-8 data when " << operation_str << " a protocol "

<< "buffer. Use the 'bytes' type if you intend to send raw "

<< "bytes. ";

}

}

运行错误是从这里输出的,关键还是在于IsStructurallyValidUTF8这个函数,实现在structurally_valid.cc里:

bool IsStructurallyValidUTF8(const char* buf, int len) {

if (!module_initialized_) return true;


int bytes_consumed = 0;

UTF8GenericScanFastAscii(&utf8acceptnonsurrogates_obj,

buf, len, &bytes_consumed);

return (bytes_consumed == len);

}

这里逐个字符扫描是否符合utf-8规范,比如110xxxxx 10xxxxxx这样,具体可以参考utf-8的编码标准。

反序列化过程类似。

看到这里我们可以得到这样的结论:

  1. protobuf里的string/bytes在C++接口里实现上都是std::string。
  2. 两者序列化、反序列化格式上一致,不过对于string格式,会有一个utf-8格式的检查。

出于效率,我们应当在确定字段编码格式后直接使用bytes,减少utf8编码的判断,效率上会有提高。

注意以上代码在pb2.6下,2.4不会输出field_name。

据了解java接口上有一定的区别,分别对应String以及ByteString。

深入探讨Protobuf中string与bytes类型的UTF-8验证机制及性能优化 本文深入解析了Protobuf中string与bytes类型的核心区别,重点探讨了C++实现中UTF-8验证的触发时机与机制。通过源码分析揭示了string类型在解析时进行严格UTF-8校验的原理,而bytes类型则无此限制。文章结合性能测试与实战场景,为开发者提供了在高性能与数据安全间选择合适类型的清晰指南。 阅读详情

相关推荐

protobuf支持非UTF8字符串

protobuf支持非UTF8字符串 protobuf规范string类型是必须是UTF8字符,但在C/C++中可以直接调用set方法设置任意编码方式的字符串,也可以直接取得对应字符串,但在控制台中会打印出编码不是UTF8字符的错误信息. 查看protobuf源代码发现是在wire_format.h中有一函数VerifyUTF8String()里进行编码判断的,

chaimyu的专栏 1万+

protobuffer中string和bytes类型

博客搬家,原地址:https://langzi989.github.io/2017/06/07/protoBuffer中string与byte类型区别/ 从上一节protobuffer的介绍中我们知道字符串类型在protobuffer中有string和bytes两种类型,那这两种类型有什么区别呢,什么时候用string,什么时候用bytes。在C++中两种类型分别对应的是什么类型.下面将揭开迷雾 ...

langzi989的专栏 1万+

Protobuf数据类型深度对比:为什么你的非UTF-8数据应该用bytes而不是string

本文深入剖析了Protobuf中string与bytes数据类型的本质区别。string被定义为UTF-8编码的文本,而bytes用于存储任意字节序列。在处理非UTF-8数据(如加密内容或序列化对象)时,必须使用bytes类型,以避免跨语言解析时的“invalid UTF-8 data”错误,并确保数据完整性与系统兼容性。

weixin_29001419的博客 214

Protobuf 25.3系列4- c++使用bytes踩坑,0x00问题

例如序列化后Hexadecimal String: 086518012a0473656e6430bf843d380140014a0811ff1000010020ff。长度的计算不要使用strlen,否则会导致解析出来的data里00后面的数据丢失。如果data使用普通的 string,一般不会有问题。2,发送的时候,或者反序列化的时候。1,string一定要指定长度。

nuaa_yk的专栏 1966

yolov10+bytetrack实现多目标跟踪

在训练yolov10权重的时候一定要注意将类别信息改成自己的信息。把类比什么的改成自己的数据集,数据集的路径也要替换自己的路径。就可以训练自己的数据集了,训练完之后得到自己的权重文件。自己创建一个.yaml文件用于自己数据集的路径选择。工具标注自己的数据集,一定要分清楚自己的类别信息。使用以下代码可以按照比例划分自己的数据集。之后打开命令框输入以下命令进入标注页面。只需要输入好自己数据集的路径就可以开始。将代码里面的nc改成自己的真实类别。修改完之后,运行train.py。然后标注自己的数据集就行。

l15717690526的博客 1527

python 识别滑块验证码

博客来源于: https://www.cnblogs.com/wyh0923/p/16528354.html # -*- coding: utf-8 -*- # https://gov.pkulaw.cn/ 1. import io 2. import json 3. from pathlib import Path 4. from PIL import Image 5. import bas...

2102

protobuf -- string与bytes的区别

protobuf提供了多种基础数据格式,包括string/bytes。从字面意义上,我们了解bytes适用于任意的二进制字节序列。然而对C++程序员来讲,std::string既能存储ASCII文本字符串,也能存储任意多个\0的二进制序列。那么区别在哪里呢? 同时在实际使用中,我们偶尔会看到类似这样的运行错误: [libprotobuf ERROR google/protobuf/wire_format.cc:1091] String field 'str' contains invali.

mao834099514的博客 1万+

9.9华为OD机试真题 新系统 - 受限任务分配 (Java/Py/C/C++/Js/Go)

华为OD机试真题 新系统【受限任务分配】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题 【受限任务分配】多语言题解。

qq_45776114的博客 731

protobuf 中bytes与string在C++中的区别

protobuf中有string 和 bytes两种数据类型, 相对应于python中的 string和 bytes类型。但在C++ 中有::std::string 却没有bytes类型。他们之间怎么转换。 看了一些介绍得到的结论是: (1)在C++中,protobuf的string类型和bytes类型都对应与C++的::std::string类型 (2)区别是,protobuf中string 对应的 std::string 类型需进行UTF8字符的检查,而bytes对应的std::string类型

Lyncai的专栏 4844

STM32 使用SYN6288语音模块

本篇文章带大家学习一下SYN6288语音模块,这个模块可以用于车载设备,语音电子书等众多产品当中,而且这个模块支持多种编码格式,GB2312,GBK等字符编码格式。SYN6288语音合成模块是一种语音合成设备,其可实现文字转语音功能,将输入的文字信息通过内部的处理和合成,输出相对应的语音信息。SYN6288模块具有语音合成质量高、输出音质好、使用方便等特点,因此广泛应用于语音播报、语音提示、语音识别、智能家居、智能家电、安防监控等领域。支持多语言:包括中文、英文、日文、韩文等多种语言。

m0_49476241的博客 2万+

ClawManager实战:OpenClaw批量部署+精细化权限管控,运维效率拉满90%

ClawManager彻底解决了OpenClaw规模化部署的运维痛点,它不是简单的“批量部署工具”,而是一套完整的企业级管理方案——从模板配置、批量部署,到权限管控、监控审计、AI治理,覆盖OpenClaw全生命周期管理,让OpenClaw从“个人工具”升级为“企业级AI基础设施”。对于中小企业,Docker一键部署即可快速落地,无需复杂配置;对于大型企业,K8s部署支持高可用、横向扩展,结合Keycloak对接企业现有认证系统,可完美融入企业IT架构。

2601_94871597的博客 608

centos 安装protobuf (string和byes 格式区别)

麻烦大家去官网先下载 Download Protocol Buffers | Google Developers从官网跳到github Release Protocol Buffers v3.18.0 · protocolbuffers/protobuf · GitHub 下载 protobuf-cpp-3.18.0.tar.gz tar -xvf protobuf-cpp-3.18.0.tar.gz cd protobuf-3.18.0/ ./configure -prefix=/u...

qixiang2013的专栏 622

【知识分享】什么是同轴传输线结构?

同轴传输线的几何形状由中心导体组,嵌在介电材料(Dielectric)中,并且,被连续的外导体所包围,也被称为屏蔽(Shield)。内外导体有相同的几何中心轴,因此得名同轴(Coaxial)。

一只豌豆象的博客 2372

protobuf string/bytes

protobuf提供了多种基础数据格式,包括string/bytes。从字面意义上,我们了解bytes适用于任意的二进制字节序列。然而对C++程序员来讲,std::string既能存储ASCII文本字符串,也能存储任意多个\0的二进制序列。那么区别在哪里呢? 同时在实际使用中,我们偶尔会看到类似这样的运行错误:   [libprotobuf ERROR google/protobuf...

MyObject-C的专栏 2590

微信商家转账报错“当前使用用户过多,请稍后重新确认收款”解决方案

当前使用用户过多,请稍后重新确认收款”这个错误,其实就是典型的参数误处理导致的假报错。记住一句话就行👇JSAPI 场景下的package参数不要做 UrlEncode。如果你也遇到这个问题,希望这篇文章能帮你少踩一个坑。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 785

UDPProbe UDP端口存活探测(发送特征包+响应分析)、UDP服务识别

qDebug() << "收到响应:" << ip.toString() << ":" << port << " 服务:" << serviceName << " 响应长度:" << response.size();qDebug() << "开始探测:" << targetIp << ":" << port << " 超时时间:" << timeout << "ms";qInfo() << "\n==================== UDP探测结果 ====================";

寒寒豆豆软件公司的博客 147

Protobuf的string和bytes在C++里竟然都是std::string?深入源码看UTF-8校验的代价

本文深入解析了Protobuf中string与bytes类型在C++实现中的核心差异。虽然两者在生成的C++代码中都映射为std::string,但string类型在序列化/反序列化时会进行严格的UTF-8编码校验,这会带来一定的性能开销。通过源码分析揭示了校验机制,并探讨了在保证数据语义清晰的前提下,如何根据场景选择类型以优化性能。

bb456的博客 866

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Protobuf实战:C++中string与bytes类型的选择与性能优化指南

本文深入探讨了在C++中使用Protocol Buffers时,string与bytes类型的选择策略与性能优化。核心区别在于string类型强制进行UTF-8验证,而bytes类型则用于存储任意字节序列,无验证开销。文章通过源码分析和性能对比,为高性能场景(如二进制数据传输、核心路径优化)提供了明确的决策指南和实战技巧,帮助开发者避免常见陷阱,实现协议清晰性与执行效率的最佳平衡。

desk3的博客 758

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

深入探讨Protobuf中string与bytes类型的UTF-8验证机制及性能影响

本文深入剖析了Protobuf中string与bytes类型在UTF-8验证机制上的核心差异及其对性能的影响。通过线上故障案例,揭示了string类型在反序列化时会进行严格的UTF-8验证,而bytes类型则视为纯二进制数据。文章对比了二者在序列化/反序列化时的性能开销,并为开发者提供了基于数据语义(文本或二进制)进行类型选型的最佳实践指南,以避免常见陷阱并优化系统性能。

weixin_29011395的博客 436

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Protobuf实战:C++中string与bytes的正确使用姿势(附UTF-8避坑指南)

本文深入探讨了在C++中使用Protocol Buffers时string与bytes类型的正确选择与性能优化。通过分析UTF-8验证机制、底层实现差异及常见问题场景,提供了实用的解决方案和性能优化建议,帮助开发者避免编码错误并提升数据处理效率。

websocket5live的博客 194

protobuf c++ 序列化为string_从前端的角度理解 Protobuf

Protocol Buffer 是什么 Protocol Buffers are a language-neutral, platform-neutral, extensible way of serializing structured data for use in communications protocols, data storage, and more, originally des...

weixin_39923945的博客 1680

Protobuf性能杀手:为什么string是最贵的类型?

在分布式系统和微服务架构中,数据序列化是影响传输效率和资源消耗的关键环节。Protobuf作为高效的二进制编码协议,其编码原理决定了不同字段类型在运行时开销差异巨大。其中,string类型由于需要处理UTF-8校验、对象创建与内存分配,往往成为反序列化耗时和内存占用飙升的隐形元凶。当字符串被用作高频访问的key、重复拼接的字段或透传的数据载体时,其昂贵代价尤为突出。理解string与bytes、enum在编码格式上的本质区别,合理利用varint、枚举映射和嵌套message等替代方案,能够显著降低序列化字

weixin_29895109的博客 313
上一篇: 为BOOST的ASIO增加“条件变量”实现协程间通讯
下一篇: Python和C/C++互相调用(embedding extending)
章志强
博客等级 码龄15年 523粉丝 93原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值