Go Down

Topic: A Simple Function for Reading CSV Text Files. (Read 20767 times) previous topic - next topic

fat16lib

Aug 09, 2015, 06:08 pm Last Edit: Aug 09, 2015, 10:00 pm by fat16lib
Here is a simple function for reading CSV text files one field at a time.

It only requires a character array two bytes longer than the longest field.

It is protected from long fields and does not use dynamic memory, like the String type.

Most of the program illustrates features of the readField() function.

Code: [Select]

// Function to read a text file one field at a time.
//
#include <SPI.h>
#include <SD.h>
#define CS_PIN 10

File file;

/*
 * Read a file one field at a time.
 *
 * file - File to read.
 *
 * str - Character array for the field.
 *
 * size - Size of str array.
 *
 * delim - String containing field delimiters.
 *
 * return - length of field including terminating delimiter.
 *
 * Note, the last character of str will not be a delimiter if
 * a read error occurs, the field is too long, or the file
 * does not end with a delimiter.  Consider this an error
 * if not at end-of-file.
 *
 */
size_t readField(File* file, char* str, size_t size, char* delim) {
  char ch;
  size_t n = 0;
  while ((n + 1) < size && file->read(&ch, 1) == 1) {
    // Delete CR.
    if (ch == '\r') {
      continue;
    }
    str[n++] = ch;
    if (strchr(delim, ch)) {
        break;
    }
  }
  str[n] = '\0';
  return n;
}
//------------------------------------------------------------------------------
#define errorHalt(msg) {Serial.println(F(msg)); while(1);}
//------------------------------------------------------------------------------
void setup() {
  Serial.begin(9600);

  // Initialize the SD.
  if (!SD.begin(CS_PIN)) errorHalt("begin failed");

  // Create or open the file.
  file = SD.open("READTEST.TXT", FILE_WRITE);
  if (!file) errorHalt("open failed");

  // Rewind file so test data is not appended.
  file.seek(0);

  // Write test data.
  file.print(F(
    "field_1_1,field_1_2,field_1_3\r\n"
    "field_2_1,field_2_2,field_2_3\r\n"
    "field_3_1,field_3_2\r\n"           // missing a field
    "field_4_1,field_4_2,field_4_3\r\n"
    "field_5_1,field_5_2,field_5_3"     // no delimiter
    ));

  // Rewind the file for read.
  file.seek(0);

  size_t n;      // Length of returned field with delimiter.
  char str[20];  // Must hold longest field with delimiter and zero byte.
  
  // Read the file and print fields.
  while (true) {
    n = readField(&file, str, sizeof(str), ",\n");

    // done if Error or at EOF.
    if (n == 0) break;

    // Print the type of delimiter.
    if (str[n-1] == ',' || str[n-1] == '\n') {
      Serial.print(str[n-1] == ',' ? F("comma: ") : F("endl:  "));
      
      // Remove the delimiter.
      str[n-1] = 0;
    } else {
      // At eof, too long, or read error.  Too long is error.
      Serial.print(file.available() ? F("error: ") : F("eof:   "));
    }
    // Print the field.
    Serial.println(str);
  }
  file.close();
}
//------------------------------------------------------------------------------
void loop() {
}



Here is optput from the program.
Quote
comma: field_1_1
comma: field_1_2
endl:  field_1_3
comma: field_2_1
comma: field_2_2
endl:  field_2_3
comma: field_3_1
endl:  field_3_2
comma: field_4_1
comma: field_4_2
endl:  field_4_3
comma: field_5_1
comma: field_5_2
eof:   field_5_3
Each line of output indicates the type of delimiter, a colon, followed by the field text.

robtillaart

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

fat16lib

#2
Aug 09, 2015, 09:45 pm Last Edit: Aug 09, 2015, 10:04 pm by fat16lib
Here is an example that reads numbers from a CSV file into a two dimensional array.

All the error checks may obscure the example.  Sorry but it's best to check for bad input.

Code: [Select]

// Example to read a two dimensional array.
//
#include <SPI.h>
#include <SD.h>
#define CS_PIN 10

// 5 X 4 array
#define ROW_DIM 5
#define COL_DIM 4

File file;

/*
 * Read a file one field at a time.
 *
 * file - File to read.
 *
 * str - Character array for the field.
 *
 * size - Size of str array.
 *
 * delim - String containing field delimiters.
 *
 * return - length of field including terminating delimiter.
 *
 * Note, the last character of str will not be a delimiter if
 * a read error occurs, the field is too long, or the file
 * does not end with a delimiter.  Consider this an error
 * if not at end-of-file.
 *
 */
size_t readField(File* file, char* str, size_t size, char* delim) {
  char ch;
  size_t n = 0;
  while ((n + 1) < size && file->read(&ch, 1) == 1) {
    // Delete CR.
    if (ch == '\r') {
      continue;
    }
    str[n++] = ch;
    if (strchr(delim, ch)) {
        break;
    }
  }
  str[n] = '\0';
  return n;
}
//------------------------------------------------------------------------------
#define errorHalt(msg) {Serial.println(F(msg)); while(1);}
//------------------------------------------------------------------------------
void setup() {
  Serial.begin(9600);

  // Initialize the SD.
  if (!SD.begin(CS_PIN)) {
    errorHalt("begin failed");
  }
  // Create or open the file.
  file = SD.open("READNUM.TXT", FILE_WRITE);
  if (!file) {
    errorHalt("open failed");
  }
  // Rewind file so test data is not appended.
  file.seek(0);

  // Write test data.
  file.print(F(
    "11,12,13,14\r\n"
    "21,22,23,24\r\n"
    "31,32,33,34\r\n"
    "41,42,43,44\r\n"
    "51,52,53,54"     // Allow missing endl at eof.
    ));

  // Rewind the file for read.
  file.seek(0);

  // Array for data.
  int array[ROW_DIM][COL_DIM];
  int i = 0;        // First array index.
  int j = 0;        // Second array index
  size_t n;         // Length of returned field with delimiter.
  char str[20];     // Must hold longest field with delimiter and zero byte.
  char *ptr;        // Test for valid field.
  char delim = 0;   // Delimiter from previous line. Start with no delimiter.

  // Read the file and store the data.
  while (true) {
    n = readField(&file, str, sizeof(str), ",\n");

    // Read error or at EOF.
    if (n == 0) {
      break;
    }
    // Advance indices based on previous delimiter.
    if (delim == '\n') {
      // previous delimiter was endl so start a new row.
      if (++i >= ROW_DIM) {
        errorHalt("too many lines");
      }
      if (j != (COL_DIM - 1)) {
        errorHalt("missing field");
      }
      j = 0;
    } else if (delim == ',') {
      // previous delimiter was comma so advance column.
      if (++j >= COL_DIM) {
        errorHalt("too many fields");
      }
    }
    array[i][j] = strtol(str, &ptr, 10);
    if (ptr == str) {
      errorHalt("bad number");
    }
    // Skip any blanks after number.
    while (*ptr == ' ') {
      ptr++;
    }
    // Save delimiter.
    delim = *ptr;

    if (delim != ',' && delim != '\n' && delim != 0) {
      errorHalt("extra data in field");
    }
    if (delim == 0 && file.available() != 0) {
      errorHalt("read error or long line");
    }
  }
  // Check that entire array was read.
  if (j != (COL_DIM - 1) || i != (ROW_DIM - 1)) {
    errorHalt("missing data");
  }
  // Print the array.
  for (i = 0; i < ROW_DIM; i++) {
    for (j = 0; j < COL_DIM; j++) {
      if (j) {
        Serial.print(' ');
      }
      Serial.print(array[i][j]);
    }
    Serial.println();
  }
  Serial.println("Done");
  file.close();
}
//------------------------------------------------------------------------------
void loop() {
}


Here is what the output should look like.
Quote
11 12 13 14
21 22 23 24
31 32 33 34
41 42 43 44
51 52 53 54
Done


fat16lib

#3
Aug 10, 2015, 03:34 pm Last Edit: Aug 10, 2015, 04:09 pm by fat16lib
Here is a simpler read array example.  It has sufficient error checking for most users.

Code: [Select]

// Example to read a two dimensional array.
//
#include <SPI.h>
#include <SD.h>
#define CS_PIN 10

// 5 X 4 array
#define ROW_DIM 5
#define COL_DIM 4

File file;

/*
 * Read a file one field at a time.
 *
 * file - File to read.
 *
 * str - Character array for the field.
 *
 * size - Size of str array.
 *
 * delim - String containing field delimiters.
 *
 * return - length of field including terminating delimiter.
 *
 * Note, the last character of str will not be a delimiter if
 * a read error occurs, the field is too long, or the file
 * does not end with a delimiter.  Consider this an error
 * if not at end-of-file.
 *
 */
size_t readField(File* file, char* str, size_t size, char* delim) {
  char ch;
  size_t n = 0;
  while ((n + 1) < size && file->read(&ch, 1) == 1) {
    // Delete CR.
    if (ch == '\r') {
      continue;
    }
    str[n++] = ch;
    if (strchr(delim, ch)) {
        break;
    }
  }
  str[n] = '\0';
  return n;
}
//------------------------------------------------------------------------------
#define errorHalt(msg) {Serial.println(F(msg)); while(1);}
//------------------------------------------------------------------------------
void setup() {
  Serial.begin(9600);

  // Initialize the SD.
  if (!SD.begin(CS_PIN)) {
    errorHalt("begin failed");
  }
  // Create or open the file.
  file = SD.open("READNUM.TXT", FILE_WRITE);
  if (!file) {
    errorHalt("open failed");
  }
  // Rewind file so test data is not appended.
  file.seek(0);

  // Write test data.
  file.print(F(
    "11,12,13,14\r\n"
    "21,22,23,24\r\n"
    "31,32,33,34\r\n"
    "41,42,43,44\r\n"
    "51,52,53,54"     // Allow missing endl at eof.
    ));

  // Rewind the file for read.
  file.seek(0);

  // Array for data.
  int array[ROW_DIM][COL_DIM];
  int i = 0;     // First array index.
  int j = 0;     // Second array index
  size_t n;      // Length of returned field with delimiter.
  char str[20];  // Must hold longest field with delimiter and zero byte.
  char *ptr;     // Test for valid field.

  // Read the file and store the data.
  
  for (i = 0; i < ROW_DIM; i++) {
    for (j = 0; j < COL_DIM; j++) {
      n = readField(&file, str, sizeof(str), ",\n");
      if (n == 0) {
        errorHalt("Too few lines");
      }
      array[i][j] = strtol(str, &ptr, 10);
      if (ptr == str) {
        errorHalt("bad number");
      }      
      if (j < (COL_DIM-1) && str[n-1] != ',') {
        errorHalt("line with too few fields");
      }
    }
    // Allow missing endl at eof.
    if (str[n-1] != '\n' && file.available()) {
      errorHalt("missing endl");
    }    
  }

  // Print the array.
  for (i = 0; i < ROW_DIM; i++) {
    for (j = 0; j < COL_DIM; j++) {
      if (j) {
        Serial.print(' ');
      }
      Serial.print(array[i][j]);
    }
    Serial.println();
  }
  Serial.println("Done");
  file.close();
}
//------------------------------------------------------------------------------
void loop() {
}


The only extra test you might add is for extra characters in a field.  This is a slightly permissive test allowing blanks at the end of a field.  strtol skips leading white space.

Code: [Select]


      array[i][j] = strtol(str, &ptr, 10);
      if (ptr == str) {
        errorHalt("bad number");
      }
      // ADD Start
      while (*ptr == ' ') {
        ptr++;
      }
      if (*ptr != ',' && *ptr != '\n' && *ptr != '\0') {
        errorHalt("extra characters in field");
      }
      // ADD End

Gerihatrick

I have very successfully used  this code for reading CSV lines on the serial monitor, from a SD card.

Serial.println(str);
Outputs the line from the card beautifully , but I now need to convert this (str) line into an array[] or something such that I can extract the individual ASCII fields and parse them to char/ints/floats. If this str was a literal "   blah blah 4.92 etc " I could do this parsing but I have tried long and hard to convert this pointer array (?) to something I can manipulate, and I have so far failed.
Can somebody please point me in the right direction  - preferably not the river.
Thanks in anticipation
Regards
Gerry


fat16lib

#5
Aug 24, 2015, 11:58 pm Last Edit: Aug 24, 2015, 11:59 pm by fat16lib
Post #3 above converts a CSV file to an array of integers using strtol() to convert the string field to a long.  This works for arrays of type int or type long.

Use strtoul() to convert the string to unsigned int or unsigned long.

Use strtod() to convert the string to float or double.  On AVR boards float and double are both 32-bit.

The string is just an array of char type so no conversion is needed.



Balagon

Hi Fatl16lib,

Thank for your program, I am a newbie in Arduino. I have used your program to read a data file and import it to the program but it has a very weird bug.

Here is my code:

Quote
#include <SPI.h>                 
#include <SD.h>                  // SD card


File file;

bool readLine(File &f, char* line, size_t maxLen) {
  for (size_t n = 0; n < maxLen; n++) {
    int c = f.read();
    if ( c < 0 && n == 0) return false;  // EOF
    if (c < 0 || c == '\n') {
      line[n] = 0;
      return true;
    }
    line[n] = c;
  }
  return false; // line too long
}

bool readVals(float* v1, float* v2) {
  char line[100], *ptr, *str;
  if (!readLine(file, line, sizeof(line))) {
    return false;  // EOF or too long
  }
  *v1 = strtod(line, &ptr);
  if (ptr == line) return false;  // bad number if equal
  while (*ptr) {
    if (*ptr++ == ',') break;
  }
  *v2 = strtod(ptr, &str);
  return str != ptr;  // true if number found
}

  float qnom = 1500;
  float sOc;
  float qrel;
  float qrelnew;
 
void setup(){
  float VOC[100]; // result1
  float SOC[100]; // result2
  int i = 0;

  float x, y;
  Serial.begin(9600);
  if (!SD.begin(4)) {
    Serial.println("begin error");
    return;
  }
  file = SD.open("test.csv", FILE_READ);
  if (!file) {
    Serial.println("open error");
    return;
  }
  while (readVals(&x, &y)) {
    VOC = x;
   Serial.print(VOC,4);
   Serial.print(": ");
    SOC = y;
   Serial.println(SOC,4);
    i++;
   
  }
  file.close();
  Serial.println("done");
 
  float voltage_sensor=0.0;
  float closet;
  float V;
 
  //voltage_sensor = (analogRead(A0)/1023.0)*4.97; // read the sensor voltage
  voltage_sensor = 3.2;
  V = voltage_sensor;
  Serial.println(V);
 
    closet = VOC[0];
    sOc = SOC[0];
   
 
    for ( i = 0 ; i < 99; i++) {
        if ((VOC - V) == 0) {
            sOc = SOC;
            break;
        }
        else {
           
            if ( (abs(VOC[i+1] - V)) < (abs(closet - V))) {
                closet = VOC[i+1];
                sOc = SOC[i+1];}
        }
       
    }

   int soc;
   soc = sOc*100;
   qrel = qnom*sOc;

   Serial.print("SOC:");
   Serial.print(soc);
   Serial.println("%");
   Serial.println("done");
 
}

  float voltage_sensor=0.0;
  float sensor_current=0.0;
  float deltaT = 1;
  int z;
  float t = 0.0;
 
 
void loop() {
 
  //sensor_current = (voltage_sensor - 2.5)/(0.3267); // convert the voltage to current beased on the relationship between I&V in the datasheet
    sensor_current = 3;
   
    float iread1 = sensor_current;
    delay (1000);
    float iread2 = sensor_current;

    //Serial.println(qrel);
   
    /*
    qrelnew = qrel;
    qrel = qrelnew - (((iread1+iread2)/2)*1000*(deltaT/3600));
    sOc = (qrel)/(qnom);
    z = sOc*100;
    Serial.print("SOC: "); // shows the voltage measured
    Serial.print(z); // the '3' after voltage allows you to display 3 digits after decimal point
    Serial.println("%");
    */
       
        /*
        if (qrel<=0) {
          voltage_sensor = 0;
          sensor_current=0;
          iread1 = 0;
          iread2 = 0;
        }

        if ((iread1 >=0)&&(iread2>=0)) {
            t = ((qrel*60)/(iread2*1000));
        }
        else if ((iread1 < 0)&&(iread2 < 0)) {
            t = (((qnom - qrel)*60)/(-iread2*1000));
        }

       
    Serial.print("Time Remaining: "); // shows the voltage measured
    Serial.print(t); // the '3' after voltage allows you to display 3 digits after decimal point
    Serial.println(" mins");
    delay(1000);
    */
   
  }
The above code works well (I did comment out almost void loop). However, when I go to the void loop, it occurs an error, and I can not open the file any more. I really dont understand because the void loop did not use the file from sd card to work, so why it can not work and the file could not able to read any more?

Thank you so much for your help, it is very important for me and I could not looking for anyone to help me.

Here is the code want to run, and it has the error:
Quote
#include <SPI.h>                 
#include <SD.h>                  // SD card


File file;

bool readLine(File &f, char* line, size_t maxLen) {
  for (size_t n = 0; n < maxLen; n++) {
    int c = f.read();
    if ( c < 0 && n == 0) return false;  // EOF
    if (c < 0 || c == '\n') {
      line[n] = 0;
      return true;
    }
    line[n] = c;
  }
  return false; // line too long
}

bool readVals(float* v1, float* v2) {
  char line[100], *ptr, *str;
  if (!readLine(file, line, sizeof(line))) {
    return false;  // EOF or too long
  }
  *v1 = strtod(line, &ptr);
  if (ptr == line) return false;  // bad number if equal
  while (*ptr) {
    if (*ptr++ == ',') break;
  }
  *v2 = strtod(ptr, &str);
  return str != ptr;  // true if number found
}

  float qnom = 1500;
  float sOc;
  float qrel;
  float qrelnew;
 
void setup(){
  float VOC[100]; // result1
  float SOC[100]; // result2
  int i = 0;

  float x, y;
  Serial.begin(9600);
  if (!SD.begin(4)) {
    Serial.println("begin error");
    return;
  }
  file = SD.open("test.csv", FILE_READ);
  if (!file) {
    Serial.println("open error");
    return;
  }
  while (readVals(&x, &y)) {
    VOC = x;
   Serial.print(VOC,4);
   Serial.print(": ");
    SOC = y;
   Serial.println(SOC,4);
    i++;
   
  }
  file.close();
  Serial.println("done");
 
  float voltage_sensor=0.0;
  float closet;
  float V;
 
  //voltage_sensor = (analogRead(A0)/1023.0)*4.97; // read the sensor voltage
  voltage_sensor = 3.2;
  V = voltage_sensor;
  Serial.println(V);
 
    closet = VOC[0];
    sOc = SOC[0];
   
 
    for ( i = 0 ; i < 99; i++) {
        if ((VOC - V) == 0) {
            sOc = SOC;
            break;
        }
        else {
           
            if ( (abs(VOC[i+1] - V)) < (abs(closet - V))) {
                closet = VOC[i+1];
                sOc = SOC[i+1];}
        }
       
    }

   int soc;
   soc = sOc*100;
   qrel = qnom*sOc;

   Serial.print("SOC:");
   Serial.print(soc);
   Serial.println("%");
   Serial.println("done");
 
}

  float voltage_sensor=0.0;
  float sensor_current=0.0;
  float deltaT = 1;
  int z;
  float t = 0.0;
 
 
void loop() {
 
  //sensor_current = (voltage_sensor - 2.5)/(0.3267); // convert the voltage to current beased on the relationship between I&V in the datasheet
    sensor_current = 3;
   
    float iread1 = sensor_current;
    delay (1000);
    float iread2 = sensor_current;

    //Serial.println(qrel);
   
   
    qrelnew = qrel;
    qrel = qrelnew - (((iread1+iread2)/2)*1000*(deltaT/3600));
    sOc = (qrel)/(qnom);
    z = sOc*100;
    Serial.print("SOC: "); // shows the voltage measured
    Serial.print(z); // the '3' after voltage allows you to display 3 digits after decimal point
    Serial.println("%");
   
       
        /*
        if (qrel<=0) {
          voltage_sensor = 0;
          sensor_current=0;
          iread1 = 0;
          iread2 = 0;
        }

        if ((iread1 >=0)&&(iread2>=0)) {
            t = ((qrel*60)/(iread2*1000));
        }
        else if ((iread1 < 0)&&(iread2 < 0)) {
            t = (((qnom - qrel)*60)/(-iread2*1000));
        }

       
    Serial.print("Time Remaining: "); // shows the voltage measured
    Serial.print(t); // the '3' after voltage allows you to display 3 digits after decimal point
    Serial.println(" mins");
    delay(1000);
    */
   
  }

Balagon

#7
Oct 03, 2015, 05:42 pm Last Edit: Mar 19, 2018, 01:37 pm by Balagon
I attached the data file for you, just in case you need it. Thank you very much. Trungdo is a funny kid :))))))).

gmunday19

Could someone tell me how I could do the same thing but with string?..


for example the csv contains

31,hello,world
32,bye,world

PaulS

Quote
Could someone tell me how I could do the same thing but with string?..
Exactly the same way, except don't call the function to convert the string to a numeric value.
The art of getting good answers lies in asking good questions.

zacpullen

Hi Guys,

Thanks for the discussion about the code. I am trying to implement the data that I have imported from the SD.

How can I access the stored data for use in a program?
 
I can somewhat access data by using for ecample "array[2][3];" which should from what I understand return the value from column 2 row 3, this dosen't seem to be the case and I am getting numbers from different areas of the array.

Any help to integrate this code would very much be of assistance.

Thanks
Zac

fat16lib

You might want to look at the new SdFat readCsv example.

This example has functions to read csv fields.  Functions are included for text, float, double, int16_t int32_t, uint16_t, and uint32_t.

It will work with SD.h, the official wrapper for a six year old version of SdFat or new versions of SdFat.

berlogi

How can I have dynamic COL_DIM ?
Thank you

berlogi

How can I have dynamic COL_DIM ?
Thank you
IF someone need it

Code: [Select]


// Example to read a two dimensional array.
//
#include <SPI.h>
#include <SD.h>
#define CS_PIN 48

// 5 X 4 array
#define ROW_DIM 5
long COL_DIM;

File file;

size_t readField(File* file, char* str, size_t size, char* delim) {
  char ch;
  size_t n = 0;
  while ((n + 1) < size && file->read(&ch, 1) == 1) {
    // Delete CR.
    if (ch == '\r') {
      continue;
    }
    str[n++] = ch;
    if (strchr(delim, ch)) {
        break;
    }
  }
  str[n] = '\0';
  return n;
}
//------------------------------------------------------------------------------
#define errorHalt(msg) {Serial.println(F(msg)); while(1);}
//------------------------------------------------------------------------------
void setup() {
  Serial.begin(9600);

  // Initialize the SD.
  if (!SD.begin(CS_PIN)) {
    errorHalt("begin failed");
  }
  // Create or open the file.
  file = SD.open("TEST.TXT", FILE_WRITE);
  if (!file) {
    errorHalt("open failed");
  }
  // Rewind file so test data is not appended.
  file.seek(0);

  /////////////////////////////////////////////////////////  
  
  File dataFile = SD.open("TEST.TXT");
  // if the file is available, write to it:
  if (dataFile) {
    while (dataFile.available()) {
      String stringOne = dataFile.readStringUntil('\n');
      int stringOneLenght = stringOne.length();
      String stringTwo = stringOne;
      stringTwo.replace(",", "");
      int stringTwoLenght = stringTwo.length();
      int COL_NUM = stringOneLenght - stringTwoLenght;
      COL_DIM = COL_NUM + 1;
      dataFile.close();
    }
  }
      
  ////////////////////////////////////////////////////////
  

  // Array for data.
  int array[ROW_DIM][COL_DIM];
  int i = 0;        // First array index.
  int j = 0;        // Second array index
  size_t n;         // Length of returned field with delimiter.
  char str[20];     // Must hold longest field with delimiter and zero byte.
  char *ptr;        // Test for valid field.
  char delim = 0;   // Delimiter from previous line. Start with no delimiter.

  // Read the file and store the data.
  while (true) {
    n = readField(&file, str, sizeof(str), ",\n");

    // Read error or at EOF.
    if (n == 0) {
      break;
    }
    // Advance indices based on previous delimiter.
    if (delim == '\n') {
      // previous delimiter was endl so start a new row.
      if (++i >= ROW_DIM) {
        errorHalt("too many lines");
      }
      if (j != (COL_DIM - 1)) {
        errorHalt("missing field");
      }
      j = 0;
    } else if (delim == ',') {
      // previous delimiter was comma so advance column.
      if (++j >= COL_DIM) {
        errorHalt("too many fields");
      }
    }
    array[i][j] = strtol(str, &ptr, 10);
    if (ptr == str) {
      errorHalt("bad number");
    }
    // Skip any blanks after number.
    while (*ptr == ' ') {
      ptr++;
    }
    // Save delimiter.
    delim = *ptr;

    if (delim != ',' && delim != '\n' && delim != 0) {
      errorHalt("extra data in field");
    }
    if (delim == 0 && file.available() != 0) {
      errorHalt("read error or long line");
    }
  }
  // Check that entire array was read.
  if (j != (COL_DIM - 1) || i != (ROW_DIM - 1)) {
    errorHalt("missing data");
  }
  // Print the array.
  for (i = 0; i < ROW_DIM; i++) {
    for (j = 0; j < COL_DIM; j++) {
      if (j) {
        Serial.print(' ');
      }
      Serial.print(array[i][j]);
    }
    Serial.println();
  }
  Serial.println("Done");
  file.close();
}
//------------------------------------------------------------------------------
void loop() {
}

Go Up