Read SD

Hey all,

Have been having fun with a micro SD in my ethernet sheild on a Mega 2560.

My question is to do with reading info back off of the SD once you've written it on.

I've seen use of:
myFile.read()
sdin.getline()

I've used both with varying levels of success. I would like to read a file which has the following format

long,float,float
long,float,float
etc.

so I am basically trying to read a line, and then break up the line at the commas or line ends. I have this so far:

while (sdin.getline(buffer, line_buffer_size,'\n') || sdin.gcount()) {
    int count = sdin.gcount();
    if (sdin.fail()) {
      cout << "Partial long line";
      sdin.clear(sdin.rdstate() & ~ios_base::failbit);
    } else if (sdin.eof()) {
      cout << "Partial final line";  // sdin.fail() is false
    } else {
      //before the contents of the buffer is printed out
      //convert sections of buffer separated by commas to indvidual values
      //call chars in the buffer indvidually
      cout << "Line " << ++line_number << endl ;
      for(int i=0; (i < (count+1)); i++) {
        if((buffer[i] == ',') || (buffer[i] == '\n')){
          
          cout << "Value " << ++value_number << " is " << values << endl ;
          j=0 ;
        }
        //if it isn't a comma or new line then use it as a char in the values[] array 
        else{
          values[j] = buffer[i] ;
          //increment the position in the value[] array for next time
          j++ ;
        }
        //if the char is a comma, then convert the value[] array to a number.
      }
      count--;  // Don’t include newline in displayed count
      value_number = 0 ; //reset this for the next line
      cout << " (" << count << " chars): " << buffer << endl ;
    }
  }
}

but get all sorts of random responses. I was wondering if there was an easier way to do it? or a way of tidying up what I am trying to do above?

Many thanks!

but get all sorts of random responses.

What is in the file? What "random" responses do you get?

Where does the program file? Is the data read from the file correctly? Is it parsed correctly? Why are you not using strtok() to parse the data?

This sketch

#include <SdFat.h>

ArduinoOutStream cout(Serial);
SdFat sd;

#define error(msg) sd.errorHalt_P(PSTR(msg))

void parseFile() {
  long l;
  float f1, f2;
  char c1, c2;
  ifstream sdin("YOURFILE.TXT");
  if (!sdin.is_open()) error("open");
  while (sdin >> l >> c1 >> f1 >> c2 >> f2) {
    if (c1 != ',' || c2 != ',') error("comma");
    cout << l << ' ' << f1 << ' ' << f2 << endl;
  }
  if (!sdin.eof()) error("parse");
}
void setup() {
  Serial.begin(9600);
  if (!sd.init()) sd.initErrorHalt();
  parseFile();
  cout << "Done" << endl;
}
void loop() {}

will parse this file, "YOURFILE.TXT"

1,2.3,4.5
6,7.8,9.0
9,8.7,6.5

and print this

1 2.30 4.50
6 7.80 9.00
9 8.70 6.50
Done

Thanks for the input guys.

PaulS, I think the answer to most of your questions is that I'm new to it all and don't quite know what I'm doing. Although I am enjoying working through the examples for the FatSd library and learning how each one functions. I think extracting data in the way I wanted to wasn't really covered which is why I got stuck...

Which leads on to...

fat16lib, Thanks for another great example. Could perhaps add something like that to the examples folder in the next release? Really enjoying your work so far, thanks for all the effort. Also, do you have a website or something with more information for the beginner like me? Your github page has loads of the technical info but it loses people like me. Obviously you don't have to support the beginner, was just wondering if you were doing this sort of thing somewhere and I hadn't seen it?

Many thanks!

I agree, this would be a good example. I will add it to the SdFat examples.

I tried to make the I/O streams in SdFat comply with the C++ standard so you could look for online tutorials about C++ I/O like these:

http://www.cplusplus.com/doc/tutorial/files/

http://www.cstutoringcenter.com/tutorials/cpp/cpp9.php

Here is the commented version I will use as an example:

/*
 *  This example reads a simple CSV, comma-separated values, file.
 *  Each line of the file has three values, a long and two floats.
 */
#include <SdFat.h>

// SD chip select pin
const uint8_t chipSelect = SS_PIN;

// file system object
SdFat sd;

// create Serial stream
ArduinoOutStream cout(Serial);

char fileName[] = "3V_FILE.CSV";
//------------------------------------------------------------------------------
// store error strings in flash to save RAM
#define error(s) sd.errorHalt_P(PSTR(s))
//------------------------------------------------------------------------------
// read and print test file
void readFile() {
  long lg;
  float f1, f2;
  char c1, c2;
  
  // create and open input file
  ifstream sdin(fileName);
  
  // check for open error
  if (!sdin.is_open()) error("open");
  
  // read until input fails
  while (sdin >> lg >> c1 >> f1 >> c2 >> f2) {
    
    // Error in line if not commas
    if (c1 != ',' || c2 != ',') error("comma");
    
    // print in six character wide columns
    cout << setw(6) << lg << setw(6) << f1 << setw(6) << f2 << endl;
  }
  // Error in an input line if file is not at EOF.
  if (!sdin.eof()) error("readFile");
}
//------------------------------------------------------------------------------
// write test file
void writeFile() {
  ofstream sdout(fileName);
  sdout << pstr(
    "1,2.3,4.5\n"
    "6,7.8,9.0\n"
    "9,8.7,6.5\n"
    "-4,-3.2,-1\n") << flush;
    
  if (!sdout) error("writeFile");
  
  // file is closed by destructor when it goes out of scope.
}
//------------------------------------------------------------------------------
void setup() {
  Serial.begin(9600);
  
  // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
  // breadboards.  use SPI_FULL_SPEED for better performance.
  if (!sd.init(SPI_HALF_SPEED, chipSelect)) sd.initErrorHalt();
  
  // create test file
  writeFile();

  // read and print test
  readFile();  
  
  cout << "Done" << endl;
}
void loop() {}