LINUX.ORG.RU

Как правильно вычитывать строки из потока?

 


0

4

Под потоком подразумевается сокет, последовательный порт и т.д..

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

Первый вариант хорош своей простотой, но плох большим количеством вызовов read()/recv(). Второй вариант хорош тем, что число вызовов read()/recv() будет минимально, но плох тем, что можно вычитать более одной строки и тогда вокруг данных после конца строки начинается пляска с бубном.

Как вообще принято реализовывать подобные вещи?

★★

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

В 99% случаев существенной разницы между этими подходами нет. сеть, USB, даже всякие UART, SPI и I2C данные присылают пакетом, и этот пакет по-любому сохраняется в буфере. recv/read в случае чтения по одному байту из девайса просто читают из этого буфера, а не дёргают железо на каждый чих. Оверхед разве что в сисколлах. Если не гигабиты. то в общем-то не будет заметно.

Разве что RS232 с flow control может отдавать байты по одному, но нынче использование flow control редкость даже для RS232.

Stanson ★★★★★
()
Ответ на: комментарий от mittorn

У меня буфер один достаточного размера для того, чтоб вместить целиком всю строку. Если за один раз не удалось вычитать строку до конца, то при следующем чтении передаётся указатель со смещением. Таким образом в моём коде описанная ситуация невозможна.

u5er ★★
() автор топика
Ответ на: комментарий от mittorn

после обработки первой строки есть проверка, обработан ли буфер до конца. если нет, то содержимое бфера за концом строки перемещается в начало буфера и продолжается чтение по смещению. Вот код Как правильно вычитывать строки из потока? (комментарий)

u5er ★★
() автор топика

Есть куча протоколов общения, которые подразумевают общение строками, длина которых заранее не известна.
Насколько я знаю, есть 2 подхода.
Первый подход заключается в чтении по одному байту до тех пор, пока не встретится конец строки.
Как вообще принято реализовывать подобные вещи?

Недавно написал на Си программу «koi2utf.c» для преобразования текста из кодировки KOI8-R в UTF-8, которая читает данные по одному байту. Исходный текст программы «koi2utf.c»: https://0x0.st/8-a6.c
Чтение, запись буферизируется стандартной библиотекой Си построчно.

Пример использования программы:

# ---- Скачать инструкцию по установке Debian в кодировке КОИ8-Р ----

wget -q https://www.debian.org/releases/stable/amd64/install.ru.txt

cc -O2 -o koi2utf koi2utf.c

time ./koi2utf < install.ru.txt > install.utf8.txt
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES
OR OTHER LIABILITY ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

real	0m0,012s
user	0m0,012s
sys	0m0,000s


ls -l install.ru.txt install.utf8.txt
... 395960 ... install.ru.txt
... 601219 ... install.utf8.txt

# ---- time для iconv ----

time iconv -f KOI8-R -t UTF-8 install.ru.txt > install.utf8.txt

real	0m0,069s
user	0m0,005s
sys	0m0,000s

@u5er

anonymous
()