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

VCS和UVM常用编译选项

VCS编译选项 -full64 在64bit模式下编译、仿真,用于64位操作系统 -j8 指定编译器可以并行编译的进程数为8 -timescale=1ns/1ps 指定仿真时间和精度 +libext+.v+.V+.sv+.svh 识别.v、.sv、.svh等多种格式文件 -sverilog 支持system verilog 编译 -f xxx.lisf 指定包含所有设计文件列表的文件名 -top test 设置顶层模块为test。(指包含.

qq_40571921的博客 9934

番外篇:ADS功放设计实战——负载与源牵引的协同优化

本文深入探讨了ADS功放设计中负载牵引与源牵引的协同优化原理及实战技巧。通过2.4GHz Wi-Fi功放等案例,详细解析了基波阻抗迭代优化、谐波调谐高级技巧及收敛判断方法,帮助工程师显著提升功放效率至78%以上。文章特别强调ADS仿真工具的正确使用方法和实际调试经验,为射频功放设计提供实用指导。

weixin_33483304的博客 341

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万+

马达种类全解析:VCM、Stepper、Piezo 在手机相机中的驱动原理与工程差异

在现代手机影像系统中,马达承担着核心成像组件的动态调节任务,如自动对焦(AF)、光学防抖(OIS)以及变焦调节。目前主流采用三类驱动器件:VCM(Voice Coil Motor)、Stepper(步进马达)、Piezo(压电马达)。不同马达方案在结构复杂度、响应速度、功耗、驱动方式与模组厚度适配等方面差异显著,对成像系统的性能表现有直接影响。本文将结合最新旗舰设备的应用现状,系统剖析这三类驱动马达的工作原理、架构特点与工程应用经验,为工程实践中选型与调试提供参考。

努力分享一些人工智能、计算机视觉、影像等相关的知识干货! 3781

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

52、切换线性动态系统:原理、挑战与高斯和滤波解决方案

本文介绍了切换线性动态系统(SLDS)的基本原理及其在复杂时间序列建模中的应用。SLDS结合了隐马尔可夫模型的离散状态切换与线性动态系统的连续状态演化,适用于系统动态发生跳跃的场景,如化工过程监测和金融市场分析。由于精确推理在计算上不可行,文章重点阐述了高斯和滤波这一近似方法,通过有限高斯混合来逼近后验分布,并详细描述了其递归更新、权重计算与组件合并流程。同时讨论了性能评估、优化策略及常见问题的解决方案,并展望了SLDS与深度学习、在线学习和多模态融合的未来发展方向。

algae的博客 161

【GB28181】wvp-GB28181-pro++ZLMediaKit编译安装国标流媒体服务器教程(Windows平台)

本文基于ZMLMediaKit+WVP-PRO在windows平台进行编译部署GB28181平台,网上教程也比较多,都大同小异,实际操作过程中容易出错的地方也比较多:redis安装无密码,mysql安装后密码的修改以及wvp数据可的创建,配置文件侧修改,尤其是和端口相关的项,再就是运行服务时各种错误需要注意,常见的错误已经做了汇总,遇到问题大家不要怕,找到报错的地方查看定位即可。

废人一枚的博客 4479

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

CloudCompare 二次开发(17)——点云添加均匀分布的随机噪声

使用CloudCompare编程实现点云添加随机噪声。

点云侠的博客 840

protobuf string/bytes

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

MyObject-C的专栏 2590

企业级托管钱包架构设计与MPC密钥管理:基于Go语言的生产级实践

本文探讨了2026年Web3生态中企业级托管钱包的技术架构与实现方案。文章指出,传统私钥管理模式已无法满足机构级资产管理需求,而基于多方安全计算(MPC)和门限签名(TSS)的技术方案成为主流选择。研究分析了托管钱包的四层架构设计,详细解读了MPC的核心技术原理,包括分布式密钥生成(DKG)和签名协议演进。通过Go语言实现案例,展示了密钥分片管理、DKG流程和交易签名等核心模块的代码实现。文章还提出了生产部署的安全原则、容灾设计和监控体系,并讨论了密钥撤销等现存挑战及TEE融合等未来趋势。研究为构建安全、高

分享AI、区块链技术及应用,未来已来 81

基于Cesium实现,动态水面+大坝排水动画

一、绘制面状水域,使用水波纹理,进行渲染,水体透明,可以看到底色。三、使用粒子系统,将喷泉改变方向,加上重力设置,实现排水动画。二、绘制线状三维体,用作模拟大坝拦截效果。四、最后,模拟水位上升,进行淹没分析,

一醉千秋的专栏 1420

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

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

bb456的博客 866

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

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

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

desk3的博客 758

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

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

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

weixin_29011395的博客 436

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

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、付费专栏及课程。

余额充值