Протофайлы, что это такое

Обновлено: 21.11.2024

Буферы протокола — это метод сериализации данных для эффективной передачи между программами. Структура напоминает XML или JSON, но в отличие от этих более часто используемых текстовых методов сериализации, буферы протоколов предназначены для создания чрезвычайно компактных сообщений с использованием двоичного формата. Основной компромисс заключается в том, что буферы протоколов не удобочитаемы для человека, поэтому при разработке API всегда важно учитывать вариант использования. В этом посте мы рассмотрим некоторые варианты использования protobuf и познакомимся с синтаксисом.

От данных к байтам

При сериализации мы преобразуем представление данных в памяти, которое удобно для анализа и/или вычислений, в форму, которая лучше подходит для хранения и/или передачи.

Сериализация используется для отправки данных между процессами. Например, если вы когда-либо вызывали .fit() (или .train() ) в конвейере scikit-learn или модели нейронной сети внутри блокнота Jupyter, вы можете сохранить (то есть упорядочить или сбросить) эту модель в рассоле или файл HDF5. При этом вы сериализуете структуры данных (матрицы, графики и т. д.) моделей вместе с их гиперпараметрами, весовыми коэффициентами и состоянием в формате, который можно сохранить на диске.

Противоположным процессом является десериализация (деупорядочение или загрузка) структуры данных из представления на диске в память.

Это особенно полезно, если мы загружаем модель в другом процессе, например. другой блокнот или даже сервер, который будет использовать модель в API.

Методы сериализации и варианты использования

Существует множество способов сериализации данных:

  • Полуструктурированные данные (XML, JSON) предназначены для того, чтобы сбалансировать удобочитаемость для человека и машиночитаемость. XML имеет схемы и может представлять сложные иерархические данные, но является более подробным; JSON часто является выбором по умолчанию для программистов Python, потому что словари Python могут быть сопоставлены непосредственно с JSON и наоборот.
  • Форматы конфигурации (YAML, TOML) ориентированы на удобочитаемость и используются для представления простых структур, таких как строки, целые числа, логические значения, списки, карты и т. д. Хотя YAML использует пробелы для разграничения полей для синтаксического анализа, TOML предлагает некоторую гибкость. предложить однозначное сопоставление полей со словарями и хеш-таблицами.
  • Двоичные форматы (Avro, Parquet) ошибаются в машиночитаемости и скорости.

Существует тенденция к ложному выводу о конкуренции между различными стандартами сериализации. Выбор заключается не столько в выборе «правильной» универсальной техники, сколько в продуманном проектировании с учетом варианта использования и пользователя. Например:

Сценарий 1. Создание общедоступного API данных

Предпочтительный метод сериализации: JSON или XML

JSON и XML не требуют надежного контракта между серверной частью поставщика данных и потребителями данных на другом конце. Для поставщиков данных это означает, что вы можете изменить схему, добавив новые поля, не обязательно отказываясь от поддержки старых версий API. Точно так же потребители данных могут обойтись без схемы (или самой последней ее версии), потому что схема может быть выведена из удобочитаемых результатов, возвращаемых их вызовами API. Для аналитиков и специалистов по данным, которые взаимодействуют с общедоступными API, это ключевая функция.

Сценарий использования 2: облачная конфигурация

Предпочтительный метод сериализации: YAML или TOML

YAML и TOML часто используются в облачных инструментах настройки, развертывания и разработки, таких как Kubernetes и Heroku. Они удобны тем, что содержат много шаблонов, которые можно повторно использовать в разных развертываниях, и поддерживают функции документации, такие как добавление комментариев и примечаний, которые вы не можете сделать с помощью JSON.

Сценарий использования 3: вычисления на больших наборах данных

Предпочтительный метод сериализации: Avro или Parquet

Avro и Parquet используются для больших наборов данных, предназначенных для распределенных вычислений, где схема может быть автономной с данными.

Недостатки удобочитаемости

С другой стороны, удобочитаемость имеет свою цену. Во-первых, описанные выше методы сериализации не очень компактны. И как бы вы проверили и проверили, что ваши данные находятся в правильной форме, или если служба или API изменились достаточно, чтобы сломать вашу систему? Сколько времени занимает сериализация и десериализация сообщений?

Возможно, наиболее важно то, что если сообщения не будут использоваться для общения между людьми, эти затраты могут оказаться нецелесообразными, особенно если метод сериализации замедляет пропускную способность или усложняет безопасность данных.

Вот где вступают буферы протоколов!

Анатомия Protobuf

Из методов сериализации, описанных ранее в этом посте, протокольные буферы («протобуферы») относятся к категории двоичных форматов.Первоначально они были разработаны для внутреннего использования в Google для сериализации данных в плотный двоичный формат. Protobuf начинается со строго определенной структуры, которая затем компилируется в код, который можно использовать для записи и чтения из этой структуры. Этот компактный метод идеально подходит для передачи данных между программами.

Давайте рассмотрим пример того, как буферы протоколов могут играть роль в приложении машинного обучения (ML). Представьте, что наше приложение функционирует как своего рода «проводник» для сквозного приложения ML: оно обучает модели, сравнивает результаты и сохраняет лучшие из них для дальнейшего использования. Нам нужен файл буфера протокола, который определяет типовое сообщение модели для внутренней передачи системой.

1. Определите схему

Во-первых, нам нужно определить схему данных, что мы и сделаем в файле conductor.proto. Эта схема будет отображать типы данных с именами полей, представленными в виде целых чисел. Начнем с определения синтаксиса. На момент написания этой статьи буферы протокола находятся в версии 3 (выпущенной в августе 2015 года), поэтому мы напишем синтаксис = "proto3"; в верхней части нашего файла .proto. Мы также указываем пакет, в котором будет использоваться эта схема (в данном случае conductor ).

Основными компонентами буфера протокола являются сообщения. Для нашего проводника машинного обучения мы определим сообщение модели, содержащее поля, описывающие каждую из ключевых частей метаданных модели (название, тип оценщика, отметку времени и т. д.), а также фактический подготовленный оценщик .

Обратите внимание, что в сообщениях буфера протокола поля пронумерованы, чтобы обеспечить однозначную разборчивость закодированных данных. Другими словами, для сообщения модели значение поля 1 означает, что идентификатор всегда будет на первой позиции в последовательности байтов, название модели будет на второй позиции, обучающие заметки — на третьей и т. д.< /p>

2. Скомпилируйте файл

После того, как вы загрузили и установили компилятор protobuf (например, с помощью brew ), вы можете скомпилировать указанный выше файл на выбранный вами язык. Например:

… создаст conductor_pb2.py , содержащий код Python, который можно использовать для записи и чтения из схемы, определенной в conductor.proto .

Буферы протоколов не зависят от языка приложения и доступны на большом количестве языков программирования. Например, чтобы сгенерировать код Go, мы должны сделать следующее:

… который сгенерирует conductor.pb.go .

3. Применить сгенерированный код Protobuf

Теперь мы можем использовать сгенерированный код внутри нашего приложения, например, для сериализации и загрузки ранее подобранной базовой модели, чтобы гарантировать улучшение последующих моделей:

Заключительные мысли

Помимо вариантов использования, выбор способа сериализации часто сводится к компромиссу между структурой и гибкостью. Начать работу с JSON проще, чем с буферами протоколов, но сложнее поддерживать в долгосрочной перспективе. И хотя буферы протоколов сложнее изменить, чем YAML, их намного быстрее анализировать и проверять.

Использование буферов протоколов означает, что для обеспечения обратной совместимости требуется больше внимания. Назначение номеров полей сообщению в прото-файле равносильно обязательству, что эти номера не будут меняться от версии к версии. Многие опытные разработчики gRPC даже намеренно пропускают числа в своих определениях сообщений, чтобы обеспечить гибкость, а также обеспечить обратную и прямую совместимость по мере роста и развития RPC.

Если вы привыкли к парадигме RESTful API, буферы протоколов могут потребовать некоторой корректировки. Тем не менее, их определенно стоит изучить, поскольку варианты использования становятся все более распространенными. По мере того, как приложения становятся все более сложными, данные постоянно распределяются все больше, а взаимодействие с пользователем все больше зависит от промежуточной передачи данных, protobufs будут становиться все более полезными!

Эта страница знакомит вас с gRPC и буферами протоколов. gRPC может использовать буферы протоколов как в качестве языка определения интерфейса (IDL), так и в качестве базового формата обмена сообщениями. Если вы новичок в gRPC и/или буферах протоколов, прочтите это! Если вы просто хотите сначала погрузиться и увидеть gRPC в действии, выберите язык и попробуйте его Быстрый запуск.

Обзор

В gRPC клиентское приложение может напрямую вызывать метод серверного приложения на другом компьютере, как если бы это был локальный объект, что упрощает создание распределенных приложений и служб. Как и во многих системах RPC, gRPC основан на идее определения службы, определения методов, которые можно вызывать удаленно, с их параметрами и типами возвращаемых значений. На стороне сервера сервер реализует этот интерфейс и запускает сервер gRPC для обработки клиентских вызовов. На стороне клиента у клиента есть заглушка (в некоторых языках именуемая просто клиентом), которая предоставляет те же методы, что и сервер.

Клиенты и серверы gRPC могут работать и взаимодействовать друг с другом в различных средах — от серверов внутри Google до вашего собственного рабочего стола — и могут быть написаны на любом из поддерживаемых gRPC языков. Так, например, вы можете легко создать сервер gRPC на Java с клиентами на Go, Python или Ruby. Кроме того, новейшие API Google будут иметь версии своих интерфейсов gRPC, что позволит вам легко встраивать функции Google в свои приложения.

Работа с буферами протоколов

По умолчанию gRPC использует Protocol Buffers – зрелый механизм Google с открытым исходным кодом для сериализации структурированных данных (хотя его можно использовать и с другими форматами данных, такими как JSON). Вот краткое введение в то, как это работает. Если вы уже знакомы с буферами протокола, можете сразу перейти к следующему разделу.

Первым шагом при работе с буферами протоколов является определение структуры данных, которые вы хотите сериализовать в прото-файле: это обычный текстовый файл с расширением .proto. Данные буфера протокола структурированы как сообщения, где каждое сообщение представляет собой небольшую логическую запись информации, содержащую ряд пар "имя-значение", называемых полями. Вот простой пример:

Затем, после того как вы указали свои структуры данных, вы используете protoc компилятора буфера протокола для создания классов доступа к данным на предпочитаемом вами языке (языках) из вашего определения proto. Они предоставляют простые средства доступа для каждого поля, такие как name() и set_name() , а также методы для сериализации/анализа всей структуры в/из необработанных байтов. Так, например, если вы выбрали язык C++, запуск компилятора в приведенном выше примере сгенерирует класс с именем Person. Затем вы можете использовать этот класс в своем приложении для заполнения, сериализации и извлечения сообщений буфера протокола Person.

Вы определяете службы gRPC в обычных прото-файлах с параметрами метода RPC и типами возвращаемых данных, указанными в виде сообщений буфера протокола:

gRPC использует протокол protoc со специальным подключаемым модулем gRPC для создания кода из вашего прото-файла: вы получаете сгенерированный код клиента и сервера gRPC, а также обычный код буфера протокола для заполнения, сериализации и извлечения ваших типов сообщений. Вы увидите пример ниже.

Чтобы узнать больше о буферах протоколов, в том числе о том, как установить protoc с подключаемым модулем gRPC на выбранном вами языке, см. документацию по буферам протоколов .

Версии буфера протокола

В целом, несмотря на то, что вы можете использовать proto2 (текущая версия буферов протокола по умолчанию), мы рекомендуем использовать proto3 с gRPC, так как это позволяет использовать весь спектр языков, поддерживаемых gRPC, а также позволяет избежать проблем совместимости с proto2. клиенты общаются с серверами proto3 и наоборот.

Примечание. 31 декабря 2021 года мы приостановили поддержку сторонних производителей устройств, работающих с Alexa Gadgets, пока мы работаем над тем, чтобы сделать их еще лучше для разработчиков и клиентов. Пожалуйста, следите за обновлениями на портале разработчиков Amazon. А пока посетите целевые страницы Alexa Voice Service, Alexa Connect Kit и Alexa Skills Kit, чтобы узнать, как с помощью голосовой связи вы можете предоставить клиентам новый опыт.

Гаджеты обычно представляют собой устройства с ограниченными ресурсами, поэтому они не взаимодействуют напрямую с облаком Alexa. Вместо этого гаджеты взаимодействуют с устройством Echo, которое обрабатывает всю связь с облаком Alexa.

Чтобы минимизировать объем передаваемой информации, гаджет и устройство Echo обмениваются сообщениями в двоичном формате. В этом разделе объясняется, как ваш гаджет может кодировать и декодировать связанную информацию в двоичном формате и обратно.

Обзор

Когда устройство Echo и облако Alexa обмениваются директивами и событиями, они используют формат JSON. Однако, поскольку гаджеты являются устройствами с ограниченными ресурсами, устройство Echo и гаджет вместо этого обмениваются этой информацией в двоичном формате.

Чтобы облегчить кодирование и декодирование информации в двоичном формате и обратно, мы используем механизм, называемый протокольными буферами, для представления полей директив и событий платформо-независимым способом. Файл .proto похож на файл JSON тем, что представляет структурированные данные, но вы можете запустить компилятор файла .proto для создания кода, который может читать и записывать данные на выбранном вами языке программирования.

Дополнительную информацию о буферах протоколов см. в Руководстве разработчика буферов протоколов на сайте Google. Гаджеты используют версию 3 (proto3) формата буфера протокола.

Загрузки

Прежде чем приступить к написанию кода для своего гаджета, необходимо загрузить следующее:

  • Файлы Alexa Gadgets .proto: загрузите и разархивируйте файлы .proto из репозитория примеров кода Alexa Gadgets GitHub.
  • Компилятор
  • .Proto. Для Alexa Gadgets мы рекомендуем компилятор nanopb .proto, который можно загрузить с веб-сайта nanopb. Это реализация C, которая генерирует небольшой код для систем с ограниченным объемом памяти. Для обсуждения.прото-компиляторы на других языках программирования см. в разделе Создание классов на сайте Google.

Как скомпилировать файлы .proto

После загрузки и установки компилятора .proto и файлов .proto, описанных ранее, вы можете скомпилировать файлы Alexa Gadgets для создания классов доступа для директив и событий Alexa Gadgets. Затем вы используете классы доступа к дате в коде своего гаджета для кодирования и декодирования директив и событий.

Способ запуска компилятора .proto зависит от операционной системы, в которой вы запускаете компилятор, как описано далее. Дополнительные сведения об использовании компиляторов .proto см. в разделе Создание классов на сайте Google.

Окна

В этом примере показано, как создать обработчики C++ для директивы messages.setIndicator в Windows.

    В командной строке перейдите в папку Notifications\SetIndicator.

Запустите компилятор протокола, введя следующую строку:

Выходными файлами будут notificationsSetIndicatorDirective.pb.h и notificationsSetIndicatorDirective.pb.cc.

Mac и Linux

Чтобы скомпилировать все файлы Alexa Gadgets .proto на Mac и Linux, запустите сценарий оболочки в репозитории примеров кода Alexa Gadgets GitHub следующим образом:

  1. Перейдите в каталог AlexaGadgetsProtoBuf/utils вашего репозитория примеров кода Alexa Gadgets для загрузки на GitHub.
  2. Откройте compile_nanos.sh и убедитесь, что ваш компилятор nanopb .proto расположен в указанной PROTO_COMPILE_PATH .
  3. Запустите compile_nanos.sh. Это создает файлы .c и .h для всех файлов .proto Alexa Gadgets и помещает их в текущий каталог.

Если вы не хотите использовать скрипт (например, хотите скомпилировать один файл .proto), один из способов сделать это — запустить компилятор .proto в каталоге, содержащем файлы .proto и . файлы опций следующим образом:

Например, чтобы запустить компилятор .proto для notificationSetIndicatorPayload.proto, выполните следующие действия:

Формат файла .Proto

Для модульности каждая директива и событие используют три файла .proto: заголовок, полезные данные и общий файл, который импортирует файлы заголовка и полезных данных .proto. Процесс компиляции протокола объединяет их для создания окончательного кода.

Заголовок директивы является общим для всех директив, а заголовок события является общим для всех событий.

Файлы директивы .proto

В этом разделе приведены примеры трех файлов .proto, представляющих директиву.

Заголовок директивы

Формат .proto заголовка директивы, directiveHeader.proto, общий для всех директив, выглядит следующим образом:

Полезная нагрузка директивы

Для каждой директивы существует один файл полезной нагрузки .proto. Следующий файл, notificationsSetindicatorDirectivePayload.proto, является примером файла .proto для директивы messages.setIndicator:

Параметры директивы

Существует файл параметров, соответствующий файлу .proto каждой директивы, содержащей одно или несколько полей в полезной нагрузке. (Например, полезная нагрузка директивы messages.clearIndicator не содержит полей, поэтому эта директива не имеет файла параметров.) Файлы параметров не являются обязательными, но они позволяют указать максимальный размер полей в директиве. Следующий файл, notificationsSetIndicatorDirectivePayload.options, является примером файла параметров для директивы messages.setIndicator:

Общий файл директив

Каждая директива имеет файл .proto, представляющий полное сообщение, которое гаджет получает от устройства Echo. Следующий файл, notificationsSetindicatorDirective.proto, является примером файла .proto для директивы messages.setIndicator:

Proto-файлы событий

В этом разделе приведены примеры трех файлов .proto, представляющих событие.

Суффикс имени файла PROTO в основном используется для файлов в формате буфера протокола. Спецификация формата буфера протокола была создана Google. Формат файла PROTO совместим с программным обеспечением, которое может быть установлено на системной платформе Linux, Mac OS, Windows. Файлы с расширением PROTO относятся к категории файлов Developer Files. Подмножество файлов разработчика включает 1204 различных формата файлов. Самая популярная программа для работы с файлами PROTO — protobuf, но пользователи могут выбирать между двумя различными программами, поддерживающими этот формат файла. программное обеспечение protobuf было разработано Google Inc., и на его официальном веб-сайте вы можете найти дополнительную информацию о файлах PROTO или программном обеспечении protobuf.

Программы, поддерживающие расширение файла PROTO

В следующем списке перечислены программы, совместимые с файлами PROTO, которые разделены на категории 3 в зависимости от операционной системы, в которой они доступны.Файлы с суффиксом PROTO можно скопировать на любое мобильное устройство или системную платформу, но их правильное открытие в целевой системе может оказаться невозможным.

Программы, поддерживающие файл PROTO

Окна

ОС MAC

Линукс

Как открыть файл с расширением PROTO?

Проблемы с доступом к PROTO могут быть вызваны разными причинами. Что важно, все распространенные проблемы, связанные с файлами с расширением PROTO, могут решать сами пользователи. Процесс быстрый и не требует участия ИТ-специалиста. Ниже приведен список рекомендаций, которые помогут вам выявить и устранить проблемы, связанные с файлами.

Шаг 1. Загрузите и установите protobuf

Основная и наиболее частая причина, препятствующая открытию пользователями файлов PROTO, заключается в том, что в системе пользователя не установлена ​​программа, которая может обрабатывать файлы PROTO. Решение простое, просто скачайте и установите protobuf. Полный список программ, сгруппированных по операционным системам, можно найти выше. Один из самых безопасных способов загрузки программного обеспечения — использование ссылок, предоставленных официальными дистрибьюторами. Посетите веб-сайт protobuf и загрузите программу установки.

Шаг 2. Проверьте версию protobuf и при необходимости обновите

Если проблемы с открытием файлов PROTO по-прежнему возникают даже после установки protobuf, возможно, у вас устаревшая версия программного обеспечения. Проверьте веб-сайт разработчика, доступна ли более новая версия protobuf. Иногда разработчики программного обеспечения вводят новые форматы вместо уже поддерживаемых вместе с более новыми версиями своих приложений. Если у вас установлена ​​более старая версия protobuf, она может не поддерживать формат PROTO. Последняя версия protobuf должна поддерживать все форматы файлов, совместимые со старыми версиями программного обеспечения.

Шаг 3. Установите приложение по умолчанию для открытия файлов PROTO в protobuf

Если у вас установлена ​​последняя версия protobuf и проблема не устранена, выберите ее в качестве программы по умолчанию, которая будет использоваться для управления PROTO на вашем устройстве. Процесс связывания форматов файлов с приложением по умолчанию может различаться в деталях в зависимости от платформы, но основная процедура очень похожа.

Выбор приложения первого выбора в Windows

  • Нажмите правой кнопкой мыши на файл PROTO и выберите "Открыть с помощью".
  • Нажмите «Выбрать другое приложение», а затем выберите «Другие приложения».
  • Последний шаг — выбрать параметр «Искать другое приложение на этом компьютере», указав путь к папке, в которой установлен protobuf. Теперь осталось только подтвердить свой выбор, выбрав Всегда использовать это приложение для открытия файлов PROTO и нажав OK .

Выбор приложения первого выбора в Mac OS

  • Нажав правую кнопку мыши на выбранном файле PROTO, откройте меню файла и выберите Информация.
  • Найдите параметр «Открыть с помощью». Нажмите на заголовок, если он скрыт.
  • Из списка выберите соответствующую программу и подтвердите выбор, нажав Изменить для всех. .
  • Если вы выполнили предыдущие шаги, должно появиться сообщение: Это изменение будет применено ко всем файлам с расширением PROTO. Затем нажмите кнопку "Продолжить", чтобы завершить процесс.

Шаг 4. Убедитесь, что PROTO исправен

Если проблема по-прежнему возникает после выполнения шагов 1–3, проверьте, действителен ли файл PROTO. Отсутствие доступа к файлу может быть связано с различными проблемами.

1. Убедитесь, что PROTO не заражен компьютерным вирусом

Если случится так, что PROTO заражен вирусом, это может быть той причиной, которая не позволяет вам получить к нему доступ. Сканируйте файл PROTO и ваш компьютер на наличие вредоносных программ или вирусов. Если сканер обнаружил, что файл PROTO небезопасен, действуйте в соответствии с инструкциями антивирусной программы для нейтрализации угрозы.

2. Проверьте, не поврежден ли файл

Если файл PROTO был отправлен вам кем-то другим, попросите этого человека повторно отправить вам файл.Возможно, файл был скопирован ошибочно, и данные потеряли целостность, что исключает доступ к файлу. Это могло случиться, если процесс загрузки файла с расширением PROTO был прерван, и данные файла повреждены. Загрузите файл еще раз из того же источника.

3. Проверьте, есть ли у вашего аккаунта права администратора

Иногда для доступа к файлам пользователю необходимо иметь права администратора. Выйдите из своей текущей учетной записи и войдите в учетную запись с достаточными правами доступа. Затем откройте файл формата буфера протокола.

4. Убедитесь, что ваше устройство соответствует требованиям для возможности открытия protobuf

Если система перегружена, она может не справиться с программой, которую вы используете для открытия файлов с расширением PROTO. В этом случае закройте другие приложения.

5. Проверьте наличие последних обновлений операционной системы и драйверов

Обновленная система и драйверы не только делают ваш компьютер более безопасным, но также могут решить проблемы с файлом Protocol Buffer Format. Устаревшие драйверы или программное обеспечение могли привести к невозможности использования периферийного устройства, необходимого для обработки файлов PROTO.

Вы хотите помочь?

Если у Вас есть дополнительная информация о файле PROTO, мы будем признательны, если Вы поделитесь ею с нашими пользователями. Для этого воспользуйтесь формой здесь и пришлите нам свою информацию о файле PROTO.

Чуть более занимательное введение в прототипы Google

Немного более занимательное введение в прототипы Google (надеюсь). Для тех, кому надоело читать официальную документацию Google, и они хотят писать менее формальным тоном.

Зачем вообще нужны протокольные буферы

Короткий ответ: эффективная сериализация данных. Поверьте мне на слово.

Подробный ответ: технически у вас есть другие варианты сериализации данных. Давайте рассмотрим каждый из них и объясним, почему они отстойные:

  • Вариант 1. Сохраните структуры данных языка в двоичном формате и отправьте их. В конце концов, данные — это просто набор нулей и единиц. Однако этот подход может сломаться во многих отношениях; вам нужно убедиться, что код скомпилирован с точно такой же разметкой памяти, порядком байтов и т.д. Программисты даже не могут договориться о текстовом редакторе (прочитайте эту вики-статью о печально известной войне редакторов, если хотите отложить), так что это безнадежное дело.
  • Вариант 2. Напишите собственный алгоритм для кодирования элементов данных в строку (напоминайте о травмирующих воспоминаниях о сложных вопросах Leetcode о сериализации дерева). Это надежный вариант для простых данных, но когда ваши структуры данных становятся все более и более сложными, вы тратите время на изобретение велосипеда.
  • Вариант 3. Расширяемый язык разметки (XML). Это язык разметки, созданный специально для этой задачи, к тому же он (несколько) удобочитаемый для человека! К сожалению, XML известен своей нехваткой места, не говоря уже о том, что навигация по XML-структурам может стать головной болью.

Победитель (самопровозглашенный): protos!

Все внутренние приложения Google используют прототипы для сериализации данных, так что это должно иметь значение. Многие сотрудники Google даже не используют Chromebook (я инженер Google, печатаю это на своем Macbook), поэтому мы не принимаем продукты вслепую только потому, что их сделал наш работодатель.

Пример прото-сообщения (с большим количеством комментариев)

Вот сообщение .proto, представляющее данные, необходимые в адресной книге. Прокрутите вниз, чтобы увидеть мои подробные заметки о различных аспектах прото-сообщения.

Поля

Протосообщение фактически представляет собой прославленный набор полей. Так что, если вы разбираетесь в полях, вы в основном знаете, что такое прото-сообщение.

Типы полей

Работают все стандартные простые типы данных (bool, int32, int64, float, double, string… а есть ли еще?).

Если вы обрабатываете сложные данные и этих примитивных типов недостаточно, вы также можете использовать другие прото-сообщения в качестве типов полей! Обратите внимание на повторяющиеся строки PhoneNumber phone = 4; и повторные лица людей = 1; ; оба они являются полями в сообщении Person и используют сообщения PhoneNumber и Person соответственно в качестве типов полей. Эта «вложенность» позволяет так легко представлять сложные структуры данных в виде прото-сообщений.

Обязательный vs. Необязательные поля

Вы заметите, что к некоторым полям добавляется необязательный модификатор, а к другим — обязательный модификатор. Как следует из названия, необязательные поля являются необязательными, а обязательные поля обязательны. Это, наверное, одно из самых повторяющихся предложений за всю мою жизнь.

Если вам интересно, вот несколько важных нюансов:

  • обязательно: если значение для этого поля не указано, сообщение будет считаться «неинициализированным». Будь осторожен; в оптимизированных билдах пропускают обязательную проверку полей, поэтому сообщение все равно будет написано.Когда вы проанализируете неинициализированное сообщение (и потерпите неудачу), вы обнаружите, что обязательное поле не было заполнено должным образом.
  • необязательный: если необязательное поле не задано, используется значение по умолчанию (см. раздел «Значения полей по умолчанию» в этом документе). Вы можете установить собственное значение по умолчанию для простых типов полей, а также для более сложных (т. е. любых, где вы используете другое прото-сообщение в качестве типа данных, например, повторяющееся поле PhoneNumber в моем примере с адресной книгой).

Номера тегов

Полям можно присваивать разные номера. Обратите внимание на =1 и =2 в моем фрагменте кода. Это не буквальные значения полей, а уникальные идентификаторы (также известные как «теги») для каждого соответствующего поля. Компилятор взбесится, если вы попытаетесь использовать один и тот же тег для нескольких полей. Кража личных данных является серьезным преступлением.

  • 1. 15 : Используйте эти значения тега для часто заполняемых полей — они требуют на один байт меньше для кодирования, чем более высокие числа. Я знаю, что один байт звучит немного, но он может иметь большое значение.
  • 16. 2047 : В основном используйте их, когда вы используете от 1 до 15.

Значения полей по умолчанию

Все поля, если они не указаны или неизвестны, будут иметь значения по умолчанию.

  • bool: ложь
  • число ( int32 и т. д.): 0
  • строка : пустая строка
  • байты: пустые байты
  • enum : первое значение (имеет значение тега 0)
  • повторяется: пустой список

Повторяющиеся поля

Чтобы выразить «список» или «массив», создайте повторяющееся поле, добавив перед именем поля повторяющееся ключевое слово. Это позволяет повторять поле любое количество раз. Порядок значений, если он сохраняется в буфере протокола.

Противоположным повторяющимся полям является одиночное поле, но мы не указываем это явно. Это просто тип по умолчанию.

Перечисления

Если вы заранее знаете все значения, которые принимает поле, используйте тип Enum. Обратите внимание, что значение перечисления.

Пакеты

Добавьте строку package my.package.name вверху файла .proto, чтобы поместить протокольное буферное сообщение в конкретный пакет.

Пакеты помогают предотвратить конфликты имен, как и пространства имен C++ ( my.package.Person ). Будьте осторожны при импорте прототипов в другие прототипы; вам нужно указать правильное имя пакета при доступе к упакованным Protos, иначе ваш компилятор будет вас раздражать. Да, я делал это много раз. Проклятием моего существования являются неправильные операторы импорта.

Время компиляции — как заставить protoc волшебным образом создавать файлы кода из файлов proto

Файлы .proto — это круто и все такое, но нас действительно волнует создание из них файлов кода, с которыми мы действительно можем работать. Ваша программа на C++ не знает, что делать с файлом .proto.

Компилятор буфера протокола (также известный как protoc) творит чудеса и создает файл кода на любом указанном вами языке программирования. После того, как вы загрузите все, что вам нужно, и подготовите все ваши файлы .proto к работе, вызовите компилятор в своем терминале с помощью следующей команды:

protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR путь/к/file.proto

Давайте разберем, что, черт возьми, происходит в этой строке.

После того как вы запустите эту команду, вы получите эти два файла в указанном вами целевом каталоге:

  • addressbook.ph.h : файл заголовка, в котором объявляется созданный для нас протокол классов.
  • addressbook.pb.cc : реализация этих классов

API буфера протокола C++

Наш замечательный компилятор буфера протокола сгенерировал собственный API буфера протокола из нашего файла addressbook.proto! Посмотрите на весь протокол кода, сгенерированный этой командой терминала:

Компилятор создаст геттеры и сеттеры для каждого из ваших полей. Изменяемые геттеры возвращают прямой указатель на значение. Обратите внимание, что для изменяемого геттера, даже если поле не инициализировано, он просто инициализирует пустой экземпляр.

API повторяющихся полей

повторяющиеся поля получают больше, чем просто сеттеры и геттеры.

  • inline int phone_size() const; : проверьте _size вашего изменяемого поля. В данном случае это будет число телефонных номеров (что-то вроде размера массива)
  • inline const ::tutorial::Person_PhoneNumber& phone(int index) const; : Геттер. Получите конкретный номер телефона, используя его индекс.
  • inline ::tutorial::Person_PhoneNumber* mutable_phones(int index); : Сеттер. Вы можете изменить номер телефона по определенному индексу.
  • inline ::tutorial::Person_PhoneNumber* add_phones(); : позволяет добавить в сообщение новое поле телефонов. Вместо того, чтобы передавать новое значение в качестве аргумента, вы вызываете этот метод, а затем переходите к изменению вновь созданной записи, используя наш сеттер в пункте выше.

API перечислений и вложенных классов

Где находятся вложенные сообщения и перечисления, которые я определил в своем файле .proto?Для нас это будут PhoneNumber и PhoneType соответственно.

  • Где мое перечисление PhoneType? Значения перечисления имеют тип Person::PhoneType и могут быть доступны как Person::MOBILE , Person::HOME и Person::WORK .
  • Где мое вложенное сообщение PhoneNumber? Это вложенный класс, к которому можно получить доступ в Person::PhoneNumber . Технически под капотом этот класс называется Person_PhoneNumber, но наш компилятор определяет typedef, который позволяет вам обращаться к нему, как если бы это был вложенный класс. Хороший компилятор.

Стандартные методы отправки сообщений

В каждом классе сообщения есть еще БОЛЬШЕ методов, которые позволяют выполнять действия с самим сообщением, а не только с отдельными его полями. Этот компилятор буферов протокола дает вам много возможностей.

  • bool IsInitialized() const; : Проверяет, были ли установлены все обязательные поля. Если вы используете какие-либо обязательные поля, рекомендуется вызывать это, иначе ваша программа может сломаться. Честно говоря, я ленивый, поэтому кажется проще вообще никогда не использовать обязательные поля.
  • строка DebugString() const; : возвращает удобочитаемое представление сообщения. К сожалению, мы не можем читать 0 и 1, так что это очень полезный метод. Используйте его при отладке.
  • void CopyFrom(const Person& from); : перезаписывает сообщение заданными значениями сообщения. Если вы собираетесь изменить множество значений в сообщении, вы можете также вызвать этот метод вместо вызова метода установки каждого отдельного поля.
  • пусто Clear(); : Очищает все элементы обратно в пустое состояние. Чистый лист.

Синтаксический анализ и сериализация

Наконец (клянусь, я перестану вводить новые методы после этого раздела), наш прекрасный компилятор сгенерировал методы для написания и чтения сообщений.

  • bool SerializeToString(string* output) const; : Сериализирует сообщение и разрывает байты в предоставленной строке. Вам не нужно писать свой собственный алгоритм сериализации строк, так что к черту вопросы по кодировке Leetcode!
  • bool ParseFromString(константная строка и данные); : анализирует сообщение из заданной строки (так называемая десериализация).
  • bool SerializeToOstream(ostream* output); : Запись сообщения в какой-нибудь C++ ostream.
  • bool ParseFromIstream(istream* input); : анализирует сообщение из некоторого C++ istream .

Существует гораздо больше методов синтаксического анализа и сериализации, но в этом руководстве мы будем использовать именно их!

Давайте напишем сообщение

Вместо того чтобы смотреть в документацию, давайте воспользуемся нашим API буферов протоколов! Допустим, я хочу, чтобы мое приложение адресной книги записывало личные данные в файл адресной книги. Для этого мне нужно сделать следующее:

Читайте также: