0

I'm trying to read txt file (has numeric values) line by line. I used SPIFFS and I used this function

void readFile(fs::FS &fs, const char * path){
   Serial.printf("Reading file: %s\r\n", path);

   File file = fs.open(path);
   if(!file || file.isDirectory()){
       Serial.println("− failed to open file for reading");
       return;
   }
   
   int count = 0;
   Serial.println(" read from file:");

   while(file.available()){
    if (count < 100)  
      Serial.write(file.read());  
   } 
}

What is the alternative function for "file.read()" something like "readline" because I need to read the file from first line to 100 and from 101 to 200 and so on .

lena
  • 730
  • 2
  • 11
  • 23
  • 1
    https://www.arduino.cc/reference/en/language/functions/communication/stream/streamreadbytesuntil/ – Juraj Dec 15 '21 at 14:52

3 Answers3

0

To read lines from Serial, network Client, from File or other object implementing the Arduino Stream class you can use function readBytesUntil.

uint8_t lineBuffer[64];
while (file.available()) {
  int length = file.readBytesUntil('\n', lineBuffer, sizeof(lineBuffer) - 1);
  if (length > 0 && lineBuffer[length - 1] == '\r') {
    length--; // to remove \r if it is there
  }
  lineBuffer[length] = 0; // terminate the string
  Serial.println(lineBuffer);
}
Juraj
  • 3,490
  • 4
  • 18
  • 25
0

You need to use readStringUntil. Although it's not the most efficient way, i'll show you how it's done.

#include <vector>
#include <SPIFFS.h>

std::vector<double> readLine(String path, uint16_t from, uint16_t to) {
  std::vector<double> list;
  if(from > to) return list;
  File file = SPIFFS.open(path.c_str());
  if(!file) return list;
  uint16_t counter = 0;
  while(file.available() && counter <= to) {
    counter++;
    if(counter < from) {
      file.readStringUntil('\n');
    } else {
      String data = file.readStringUntil('\n');
      list.push_back(data.toDouble());
    }
  }
  return list;
}

void setup() {
  Serial.begin(115200);
  SPIFFS.begin(true);
  
  std::vector<double> numbers = readLine("file.txt", 0, 100);
  Serial.println("Data from 0 to 100:");
  uint16_t counter = 0;
  for (auto& n : numbers) {
    counter++;
    Serial.print(String(n) + "\t");
    if(counter % 10 == 0) {
      Serial.println();
    }
  }

  numbers = readLine("file.txt", 101, 200);
  Serial.println("\nData from 101 to 200:");
  counter = 0;
  for (auto& n : numbers) {
    counter++;
    Serial.print(String(n) + "\t");
    if(counter % 10 == 0) {
      Serial.println();
    }
  }
}

UPDATE

Supposed you have 1050 values and you want to parse it for each 100 values.

int i = 0;
while(i < 1050) {
  int start = i + 1;
  int end = (i + 100) > 1050 ? 1050 : i + 100;
  std::vector<double> numbers = readLine("file.txt", start, end);
  
  Serial.println("Data from " + String(start) + " to " + String(end) + ":");
  uint16_t counter = 0;
  for (auto& n : numbers) {
    counter++;
    Serial.print(String(n) + "\t");
    if(counter % 10 == 0) {
      Serial.println();
    }
  }

  i += 100;
}
Wachid Susilo
  • 496
  • 4
  • 11
  • 1
    Thank you so much, if my file contain on 1050 value and I need in each time read 100, 100,100,... , until the end of file and the last 50 values are not read because they are less than 100 how can do that? – lena Jan 11 '22 at 22:05
  • Hi @kayla , just read the data as of the following: `readLine("file.txt", 1001, 1050);` – Wachid Susilo Jan 12 '22 at 16:41
  • how can repeat this code to include all file size? std::vector numbers = readLine("file.txt", 0, 100); Serial.println("Data from 0 to 100:"); uint16_t counter = 0; for (auto& n : numbers) { counter++; Serial.print(String(n) + "\t"); if(counter % 10 == 0) { Serial.println(); } } – lena Jan 13 '22 at 08:32
  • I have updated my answer. – Wachid Susilo Jan 13 '22 at 12:15
  • Sorry, but why the output just printing Data from 1 to 100: Data from 101 to 200: Data from 201 to 300: Data from 301 to 400: Where this part does not work for (auto& n : numbers) { counter++; Serial.print(String(n) + "\t"); if(counter % 10 == 0) { Serial.println(); } } – lena Jan 13 '22 at 16:27
  • If it's not printing, then the vector is empty. If the vector is empty, then the data in SPIFFS are also empty. – Wachid Susilo Jan 13 '22 at 19:35
  • No, the data in SPIFFS are not empty! – lena Jan 13 '22 at 20:30
  • It's necessarily the SPIFFS it self doesn't contains data. What i mean is that the file you are lookong for may be empty. You should check if the file is not empty – Wachid Susilo Jan 14 '22 at 22:00
-1

The File is a Stream and has all of the methods that a Stream does, including readBytesUntil and readStringUntil.

hobbs
  • 223,387
  • 19
  • 210
  • 288