CSV-Parser-for-Arduino icon indicating copy to clipboard operation
CSV-Parser-for-Arduino copied to clipboard

Reading multiple files at the same time, row by row

Open hapiel opened this issue 2 years ago • 5 comments

It's currently not easily possible to read multiple files at the same time, when using row by row mode.

Each csv parse instance refers to the same feedRowParser() which then uses the same file:

char feedRowParser() {
  return file.read();
}
bool rowParserFinished() {
  return ((file.available()>0)?false:true);
}

I think it would be better if you can somehow set functions when creating the csv parse instance.

hapiel avatar Feb 07 '24 22:02 hapiel

That's a good point, I'll add it soon, just need to be careful to avoid breaking the old way.

michalmonday avatar Feb 07 '24 23:02 michalmonday

In the 1.4.0 version I added the following 3 methods:

cp.setRowParserFinishedCallback(func_returning_bool);

// only one of these should be used at once:
cp.setFeedRowParserCallback(func_returning_char);
cp.setFeedRowParserStrCallback(func_returning_char_pointer);

// I added "Str" version because it is faster in practice when a whole string is supplied 
// rather than single character. 

Here's a quick example I used to check if it works:


#include <CSV_Parser.h>

char * csv_str = "my_strings,my_numbers\r\n"
                 "hello,5\r\n"
                 "world,10\r\n";
int csv_str_index = 0;

char feedRowParser() {
  return csv_str[csv_str_index++];
}

bool rowParserFinished() {
  return csv_str[csv_str_index] == 0;
}

char * csv_str_2 = "another_strings,another_numbers\r\n"
                 "abcd,1\r\n"
                 "efg,2\r\n\0";
int csv_str_index_2 = 0;

char feedRowParser_2() {
  return csv_str_2[csv_str_index_2++];
}

bool rowParserFinished_2() {
  return csv_str_2[csv_str_index_2] == 0;
}
 
void setup() {
  Serial.begin(115200);
  delay(5000);
                   
  CSV_Parser cp(/*format*/ "sL");
  cp.setFeedRowParserCallback(feedRowParser);
  cp.setRowParserFinishedCallback(rowParserFinished);

  char **strings = (char**)cp[0];
  int32_t *numbers = (int32_t*)cp[1];

  int row_index = 0;
  while (cp.parseRow()) {    
    char *string = strings[0];
    int32_t number = numbers[0];

    Serial.print(String(row_index) + ". String = ");
    Serial.println(string);
    Serial.print(String(row_index) + ". Number = ");
    Serial.println(number, DEC);
    Serial.println();
    row_index++;
  }


  CSV_Parser cp_2(/*format*/ "sL");
  cp_2.setFeedRowParserCallback(feedRowParser_2);
  cp_2.setRowParserFinishedCallback(rowParserFinished_2);

  char **strings_2 = (char**)cp_2[0];
  int32_t *numbers_2 = (int32_t*)cp_2[1];

  int row_index_2 = 0;
  while (cp_2.parseRow()) {    
    char *string_2 = strings_2[0];
    int32_t number_2 = numbers_2[0];

    Serial.print(String(row_index_2) + ". String = ");
    Serial.println(string_2);
    Serial.print(String(row_index_2) + ". Number = ");
    Serial.println(number_2, DEC);
    Serial.println();
    row_index_2++;
  }  
}

void loop() {

}

And the output was as expected:

0. String = hello
0. Number = 5

1. String = world
1. Number = 10


0. String = abcd
0. Number = 1

1. String = efg
1. Number = 2

New changes should not break any previous codes relying on the "feedRowParser" and "rowParserFinished". I am planning to update examples and README.md but there are few of them so I will add them in new release.

michalmonday avatar Feb 08 '24 01:02 michalmonday

I just realized the new change is broken for normal Arduino boards (I tested it only with Esp8266 which has "functional" header file...). I deleted the release to avoid it being pushed to arduino library manager

michalmonday avatar Feb 08 '24 01:02 michalmonday

I adapted the code (in version 1.4.1) and now it should be good (hopefully).

michalmonday avatar Feb 08 '24 01:02 michalmonday

You were so fast with this, thank you!

hapiel avatar Feb 09 '24 01:02 hapiel