Stream.readStringUntil()
readStringUntil() читает символы из потока в объект String до заданного символа-терминатора — сам терминатор в результат не включается, но из потока удаляется.
Полная статья
Описание
readStringUntil() читает символы из потока и накапливает их в объект String, останавливаясь на символе-терминаторе terminator или когда истекает таймаут ожидания. Таймаут настраивается через Stream.setTimeout().
По смыслу функция близка к readBytesUntil(): обе читают до заданного символа. Разница в том, что readBytesUntil() пишет байты в уже выделенный массив, а readStringUntil() сама формирует и возвращает объект String — это удобнее, когда длина строки заранее неизвестна. Важная деталь: терминатор не входит в результат, но при этом потребляется из потока и уже не будет доступен следующему вызову.
Метод принадлежит классу Stream и наследуется всеми его потомками, в том числе Serial, Wire и сетевыми клиентами. Подробнее о классе см. на странице Stream.
Синтаксис
stream.readStringUntil(terminator)
Параметры
terminator— символ, на котором чтение прекращается. Тип данных:char.
Возвращает
Объект String с символами, прочитанными до терминатора. Если терминатор так и не пришёл, функция вернёт всё, что успела прочитать за время таймаута. Если поток был пуст, вернётся пустая строка "".
Тип данных: String.
Пример кода
В примере скетч читает из Serial одну строку до '\n':
void setup() {
Serial.begin(9600);
Serial.setTimeout(1000);
}
void loop() {
if (Serial.available()) {
String line = Serial.readStringUntil('\n');
line.trim();
Serial.print("Line: ");
Serial.println(line);
}
}
Где применяется
- Построчный ввод из Serial Monitor — принять команду, которую пользователь завершил нажатием Enter.
- Разбор CSV-подобных данных — последовательно читать поля, разделённые запятой или точкой с запятой.
- Ответы AT-команд и GPS-модулей — каждый ответ приходит строкой с известным символом в конце.
- Простые текстовые протоколы — когда каждое сообщение гарантированно заканчивается одним и тем же символом.
Практические замечания
- Терминатор не попадает в строку. Если пришла строка
"start\n", результатом будет"start". - Терминатор потребляется из потока. После успешного чтения он уже не будет виден следующему вызову
read()или любому другому методу чтения. - При таймауте возвращается частичный результат. Если терминатор так и не пришёл, функция вернёт то, что успела накопить, — это может быть неполная строка или пустой объект.
- Для данных фиксированной длины предпочтительнее
readBytes(). Когда протокол задаёт точное количество байт, а не терминатор, чтение по длине работает надёжнее и предсказуемее. - Помните про
String. Для небольших скетчей динамические строки удобны, но в долгоживущих проектах на платах с ограниченной памятью лучше работать сchar-буферами напрямую.
Примечания и предупреждения
Передавайте терминатор именно как символ в одинарных кавычках: '\n', ',', ';'. Строка "\n" имеет тип const char* — это не то же самое, что символ, и не подходит для параметра terminator.