Stop on newline when using read(…)

让人想犯罪 __ 提交于 2019-12-02 17:30:23

问题


I need to read the NMEA sentences from a GPS connected through UART. The OS is Debian, and the language must be C++. To do so I'm opening the file with open(...) and reading a string with read(...). However, this way I have to specify a string length, which breaks up the sentences. Instead I want to read until the end of the NMEA sentence. How may I use read(...) and stop on new line? Is there an option to read(...)?


回答1:


I need to read the NMEA sentences from a GPS connected through UART.
...
How may I use read(...) and stop on new line?

If you opened a terminal device (e.g. /dev/ttyUSB0), then you can use the terminal's line discipline handler to parse the received text into lines.
The terminal must be opened in blocking mode (which is the default unless non-blocking is specified), and the terminal must be configured for canonical input (using the termios API).

Is there an option to read(...)?

When the terminal device is configured for canonical input, then a read() will return a line of text (unless an error occurred). Be sure that your read buffer (and count argument) is large enough for the longest expected line, so that the read() will not truncate the line.

From the termios man page:

   Canonical and noncanonical mode  

   The setting of the ICANON canon flag in c_lflag determines whether
   the terminal is operating in canonical mode (ICANON set) or
   noncanonical mode (ICANON unset).  By default, ICANON set.

   In canonical mode:

   * Input is made available line by line.  An input line is available
     when one of the line delimiters is typed (NL, EOL, EOL2; or EOF at
     the start of line).  Except in the case of EOF, the line delimiter
     is included in the buffer returned by read(2).

   * Line editing is enabled (ERASE, KILL; and if the IEXTEN flag is
     set: WERASE, REPRINT, LNEXT).  A read(2) returns at most one line
     of input; if the read(2) requested fewer bytes than are available
     in the current line of input, then only as many bytes as requested
     are read, and the remaining characters will be available for a
     future read(2).

   * The maximum line length is 4096 chars (including the terminating
     newline character); lines longer than 4096 chars are truncated.
     After 4095 characters, input processing (e.g., ISIG and ECHO*
     processing) continues, but any input data after 4095 characters up
     to (but not including) any terminating newline is discarded.  This
     ensures that the terminal can always receive more input until at
     least one line can be read.

Use the stty command, or tcgetattr() and tcsetattr() to configure the terminal mode.
Study Setting Terminal Modes Properly and Serial Programming Guide for POSIX Operating Systems.

Note that the line returned in the read buffer is not a string, and will not be terminated with a null byte. For a solution see Linux Serial Read throws Error




回答2:


How may I use read(...) and stop on new line? Is there an option to read(...)?

No, read() has no option to do that.

Per the POSIX standard:

The read() function reads data previously written to a file. If any portion of a regular file prior to the end-of-file has not been written, read() shall return bytes with value 0. For example, lseek() allows the file offset to be set beyond the end of existing data in the file. If data is later written at this point, subsequent reads in the gap between the previous end of data and the newly written data shall return bytes with value 0 until data is written into the gap.

Upon successful completion, where nbyte is greater than 0, read() shall mark for update the last data access timestamp of the file, and shall return the number of bytes read. This number shall never be greater than nbyte. The value returned may be less than nbyte if the number of bytes left in the file is less than nbyte, if the read() request was interrupted by a signal, or if the file is a pipe or FIFO or special file and has fewer than nbyte bytes immediately available for reading. For example, a read() from a file associated with a terminal may return one typed line of data.

If a read() is interrupted by a signal before it reads any data, it shall return -1 with errno set to [EINTR].

If a read() is interrupted by a signal after it has successfully read some data, it shall return the number of bytes read.

...

read() handles raw bytes, without any interpretation.

If you want to use a library function to read lines of text data from a file, you can use the getline() function.



来源:https://stackoverflow.com/questions/36586137/stop-on-newline-when-using-read

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!