readln for Arduino - The easy way to read text from Serial, and from text files

readln for Arduino, shown reading the Serial Monitor
×
readln for Arduino, shown reading the Serial Monitor
readln for Arduino - Example reads lines of text from the Serial Monitor.

Arduino has a println function used to write text to the Serial port, or to write complete CRLF terminated text lines to files however, it doesn't have a simple opposite function to read CRLF terminated text lines from Serial and from files. Typically, reading text lines is complicated because folks use the readbyteuntil function, but then you have to remove unwanted characters before you can use the text.

With this readln for Arduino function you simply read one full line of text at a time, it reads up to the line feed, LF, character and disposes of additional carriage returns automatically. It can read both Linux style LF terminated lines, and Windows style CRLF terminated lines.

You also specify a maximum number of characters to read, typically the size of the buffer you are reading to (-1). This helps prevent buffer overruns, if there are more characters available than fit the buffer, readln returns the buffer size of characters then returns the next characters at the next read.

My specific application for readln is in ESP32 LittleFS where it is used to read, copy, and modify files that contain HTML, and text keys, e.g. keyname=value.

Usage
Example, readln reading from Serial Monitor


#define LINELEN 120
char linein[LINELEN] = "";
int ret = 0;

void setup() {
  Serial.begin(115200);
  Serial.setTimeout(10);
}

void loop() {
  ret = Serial.readln(linein, LINELEN - 1);
  if (ret > 0){
    Serial.println(linein);
  }
}

The example starts by defining the maximum length (plus one) of text to be read by readln, and creating the 'c‑string' to receive the line of text. 'ret' is an integer to receive the status from readln. Returns are -ve, an error ocurred, 0 no characters were read, a positive value, the number of characters read.

Setup starts Serial, and sets a timeout value for reads, default is one second, and loop will wait for the read to complete in each loop.

In loop a readln is initiated, and if any characters are received (ret >0) they will be written to the Serial monitor.

Note: In the Serial Monitor you can set line termination to be No line ending, New line, Carriage return, or Both NL & CR. It should be set to New line or Both NL & CR.

If you try compiling this example it will fail, becaue the readln function has to be set up first.

Setting up readln

The readln function and the readln function header have to be copied to the Stream.cpp file, and Stream.h file respectively. These files are in the board file package for the board manufacturer you are using. The packages are typically found in a folder like:

C:\Users\UserName\AppData\Local\Arduino15\packages

In my system I have boards from several manufacturers, Stream.cpp, and Stream.h files can be found in:

C:\Users\UserName\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino
C:\Users\UserName\AppData\Local\Arduino15\packages\adafruit\hardware\samd\1.7.16\cores\arduino
C:\Users\UserName\AppData\Local\Arduino15\packages\esp32\hardware\esp32\3.3.5\cores\esp32
C:\Users\UserName\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\cores\esp8266

Alternatively, you could search for 'Stream.cpp;Stream.h' using 'FileLocator Pro' which you can find at:
https://www.mythicsoft.com/
I have no affiliation with mythicsoft, I just think that Windows search is worse than useless, and FileLocator Pro is brilliant! I have used it for years, and I am still finding new ways to use it. To start you off they have a free version.

Now to make some changes, if you are not completely confident about this, don't do it (Please!)

Make a copy of the Stream.cpp, and the Stream.h files and store them in a safe place so that, in the event of issues, they can be put back where they came from.

Edit the Stream.cpp file by adding the following code between the end of the function 'readBytesUntil', and before the 'readString' function.


// as readBytes but terminates on LF (10), ignores CR (13)
// terminates if length characters have been read, timeout,
// or if the terminator character detected
// returns the number of characters placed in the buffer
// (0 means no valid data found)
int Stream::readln(char *buffer, int length) {
  int index = 0;
  int c = 0;
  while (index < length) {
    c = timedRead();
    if (c < 0 || c == 10) {
      break;
    }
    if (c != 13){
      *buffer++ = (char)c;
      index++;
    }
  }
  *buffer = '\0';
  if (c < 0){
    return -1;
  }else{
  return index; // return number of characters, not including null terminator
  }
}

Edit the Stream.h file by adding the following code between the end of the function header for 'readBytesUntil', and before the function header for 'readString'.


// as readBytes but terminates on LF (10), ignores CR (13)
// terminates if length characters have been read, timeout,
// or if the terminator character detected
// returns the number of characters placed in the buffer
// (0 means no valid data found)

int readln(char *buffer, int length);


You will need to make the above changes to the Stream files for each of the board manufacturers that you want to use readln with. Also, if the manufacturers release new versions of their software, you will have to re-apply the changes.

Enhancement Request

I have made a request for enhancement to the Stream files with Arduino but the request has been open since May 2025. If and when the enhancement is implemented by Arduino, it will then have to be implemented by each of the board manufacturers! This could take some time, which is why I implemented it myself.
I don't have many years left and, for me, the convenience of the readln function far outweighs the inconvenience of having to poke about in the system libraries.

The enhancement request is titled, 'In stream.cpp add readln, to simplify reading Windows and Linux text files #251'. And can be found at:
https://github.com/arduino/ArduinoCore-API/issues/251

Contact

My application for reading text was to read, copy, edit files containing HTML, and text key files, e.g. keyname=value. I used it in ESP32, in a LittleFS file system. If you need to read text from files, I hope that you find readln useful, if you do please add weight to the enhancement request, and let me know how you get on.
If you have issues using it, please get in touch at: comments@chisholm.nl.