使用read(...)时停止换行

时间:2016-04-12 23:55:25

标签: linux file uart

我需要从通过UART连接的GPS读取NMEA句子。操作系统是Debian,语言必须是C ++。为此,我将使用open(...)打开文件,并使用read(...)读取字符串。但是,这种方式我必须指定一个字符串长度,它会分解句子。相反,我想阅读直到NMEA句子结束。我如何使用read(...)并停在新线上?有read(...)的选项吗?

2 个答案:

答案 0 :(得分:4)

  

我需要通过UART连接的GPS读取NMEA句子   ...
  我如何使用read(...)并在新行上停止?

如果您打开终端设备(例如 / dev / ttyUSB0 ),则可以使用终端的线路规则处理程序将接收的文本解析为行。
必须以阻塞模式打开终端(除非指定了非阻塞,否则这是默认设置),并且必须为canonical input配置终端(使用termios API)。

  

是否有阅读(...)的选项?

当终端设备配置为规范输入时, read()将返回一行文本(除非发生错误)。确保您的读缓冲区(和计数参数)足够大,以获得最长的预期行,以便 read()不会截断该行。

来自termios手册页:

   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.

使用stty命令或 tcgetattr() tcsetattr()配置终端模式。
研究Setting Terminal Modes ProperlySerial Programming Guide for POSIX Operating Systems

请注意,读缓冲区中返回的行不是字符串,并且不会以空字节终止。有关解决方案,请参阅Linux Serial Read throws Error

答案 1 :(得分:0)

  

我如何使用read(...)并停在新线上?有选择吗?   read(...)

不,read()没有选择这样做。

根据POSIX standard

  

read()函数读取先前写入文件的数据。如果有的话   文件结尾之前的常规文件的一部分尚未存在   写入,read()将返回值为0的字节。例如,   lseek()允许将文件偏移量设置为超出现有值的末尾   文件中的数据。如果此时稍后写入数据,则后续   读取上一个数据结束与新数据之间的差距   写入的数据应返回值为0的字节,直到写入数据   进入差距。

     

成功完成后,nbyte大于0,read()   应标记更新文件的最后一个数据访问时间戳,以及   应返回读取的字节数。这个数字永远不会   大于nbyte。如果返回的值可能小于nbyte   如果是,则文件中剩余的字节数小于nbyte   read()请求被信号中断,或者文件是管道   或FIFO或特殊文件,并且立即少于nbyte个字节   可供阅读。例如,来自文件关联的read()   使用终端可能会返回一个类型的数据行。

     

如果read()在读取任何数据之前被信号中断,则为它   如果errno设置为[EINTR],则返回-1。

     

如果read()在成功后被信号中断   读取一些数据,它将返回读取的字节数。

     

...

read()处理原始字节,没有任何解释。

如果您想使用库函数从文件中读取文本数据行,可以使用getline() function