Главная chevron_right Функции chevron_right Связь chevron_right Stream.readBytes()

Stream.readBytes()

readBytes() читает из потока блок байтов заданной длины и записывает их в buffer, завершаясь досрочно по таймауту, если данные не поступили.

Полная статья

Описание

readBytes() читает данные из потока и записывает их в заранее подготовленный массив. Функция завершается, когда накоплено нужное количество байтов length, или раньше — если за отведённое время данные так и не поступили. Длительность ожидания задаётся через Stream.setTimeout().

Метод определён в классе Stream и работает во всех его наследниках: Serial, Wire, сетевых клиентах и других. Подробнее об этом классе — на странице Stream.

Если read() возвращает ровно один байт за вызов, то readBytes() рассчитан на ситуации, когда нужно забрать из потока сразу целый блок: заголовок пакета, массив измерений, команду фиксированной длины или фрагмент бинарного протокола.

Синтаксис

stream.readBytes(buffer, length)

Параметры

  • buffer — массив, в который будут записаны прочитанные байты. Допустимые типы: массив char или byte.
  • length — количество байтов, которое нужно попытаться прочитать. Допустимый тип: size_t.

Возвращает

Число байтов, фактически записанных в буфер. Если за время ожидания не поступило ни одного байта, функция вернёт 0.

Тип возвращаемого значения: size_t.

На что обратить внимание

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

Пример кода

В примере скетч читает до 5 символов из Serial, добавляет завершающий нулевой символ и выводит полученную строку:

char buffer[6];

void setup() {
  Serial.begin(9600);
  Serial.setTimeout(1000);
}

void loop() {
  if (Serial.available()) {
    size_t count = Serial.readBytes(buffer, 5);
    buffer[count] = '\0';

    Serial.print("Received: ");
    Serial.println(buffer);
  }
}

Где применяется

  • Фиксированные пакеты — протокол заранее задаёт длину блока: 4 байта заголовка, 8 байтов полезной нагрузки и т. д.
  • Бинарные протоколы — чтение массивов байтов без преобразования в текст, например показаний датчика в сыром виде.
  • Команды одинаковой длины — если каждая команда всегда занимает одно и то же число байтов, readBytes() проще и надёжнее посимвольного разбора.
  • Буферизация перед обработкой — сначала набрать весь блок, затем проверить контрольную сумму или разобрать поля структуры.

Практические замечания

  • Функция блокирует выполнение. Пока не накоплено length байтов или не истёк таймаут, программа стоит на месте. Учитывайте это в скетчах, где важна отзывчивость.
  • Проверяйте возвращаемое значение. Получить меньше length байтов — нормально при таймауте. Код должен корректно обрабатывать неполный пакет, а не молча использовать «мусор» в хвосте буфера.
  • Следите за размером буфера. Массив должен вмещать как минимум length байтов. Если планируете работать с результатом как с C-строкой, добавьте ещё один байт под '\0' — именно так сделано в примере выше.
  • Нулевой символ не добавляется автоматически. Для текстовых строк завершающий '\0' нужно поставить вручную после вызова функции.
  • Для данных с разделителем удобнее readBytesUntil(). Если конец сообщения отмечен специальным символом, например '\n', лучше читать до терминатора, а не рассчитывать на фиксированную длину.

Примечания и предупреждения

readBytes() хорошо работает, когда длина ожидаемых данных известна заранее. Если размер блока непредсказуем, разумнее читать поток постепенно с помощью available() и read() или использовать чтение до символа-терминатора.