Read SD data and compare to a string

First post. Been working on this problem for many days.

I have a file of telephone numbers on a SD. I need to compare that data to find out if a specific telephone number is in that file. Simple right?

I have a test sketch and have exhausted 'Google', 'Yahoo' and 'Bing' to find a answer. I have tried every example I can find and nothing works. I want to read data into an array in memory for speed but maybe that is not the way to do it.

Not sure my approach to problem is even close to what I need. Can someone point me in the right direction? I am using a DUE and should have enough memory.

Thanks, joelaw

sketch:::

#include <SD.h>
File myFile;

char Records[6200]; //String array to hold records
char inchar; //Temp variable to hold next char

int n = 0; //index variable

void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(115200);
while (!Serial)
{
}
Serial.print("Initializing SD card...");
pinMode(53, OUTPUT); //DUE pin 53 is chip select

if (!SD.begin(53)) //DUE pin 53 is chip select
{
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
// read all records into memory array "Records"
myFile = SD.open("BlkList.log", FILE_READ);

if (myFile)
{
Serial.println("FileName = BlkList.log");
// read sd data file into Records Array
while (myFile.available())
{
inchar = myFile.read();
Records[n] = inchar;
n++;
}
myFile.close();
} else
{
Serial.print("ERROR..... opening BlkList.log");
}
findNum(); //function to do lookup for telephone number
}

///////////////////////////////////////////////////
void loop()
{
// do nothing
}
//////////////////////////////////////////////////

void findNum() //function to do lookup for telephone number
{
// test example phone number
String phoneNum = "2532452465\n\r"; //full phone number
String AC = "253"; //area code only
for(int x=0; x < 6180; x + 3)
{
String ac = char((Records[x]+ Records[x+1] + Records[x+2])); // + etc.
if (AC == ac )
{
Serial.print("Found : ");
Serial.println(AC);
Serial.println(ac);
}else
{
Serial.println("Not Found");
}
}
}

Welcome to the forum. Please read the beginning "sticky" posts that explain how to post code using code tags. It helps others help you.

You did not say how the program was failing. Is it not finding the area code? Are you sure it should? Only you know what is in your data file. It is also odd that your have a telephone number followed by \n\r. On Windows machines, it is the other way around, carriage return ('\r') + newline ('\n')

You should also abandon the String class and just use regular C strings.

This untested code should work:

#include <SD.h>

const int MAX_SIZE = 6200;
char Records[MAX_SIZE];   //String array to hold records
int nbChars;            // file length, <= MAX_SIZE

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial)
  {
  }
  Serial.print("Initializing SD card...");
  pinMode(53, OUTPUT);  //DUE pin 53 is chip select

  if (!SD.begin(53))    //DUE pin 53 is chip select
  {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  // read all records into memory array "Records"

  File myFile = SD.open("BlkList.log", FILE_READ);
  if (myFile)
  {
    Serial.println("FileName = BlkList.log");
    // read sd data file into Records Array
    nbChars = 0;
    while (myFile.available())
    {
      Records[nbChars++] = myFile.read();
      if( nbChars == MAX_SIZE )
      {
        // we are out of room, so stop reading
        break;
      }
    }
    myFile.close();
  } else
  {
    Serial.print("ERROR..... opening BlkList.log");
  }
  findNum();      //function to do lookup for telephone number
}

///////////////////////////////////////////////////
void loop()
{
  // do nothing
}
//////////////////////////////////////////////////

void findNum()    //function to do lookup for telephone number
{
  // test example phone number
  //String phoneNum = "2532452465\n\r"; //full phone number
  char *AC = "253";    //area code only
  for (int x = 0; x < nbChars; x++)
  {
    if(strncmp(Records+x, AC, sizeof(AC)) == 0)     
    {
      Serial.print("Found : ");
      Serial.print(AC);
      Serial.print( " at position " );
      Serial.println(x);
    } else
    {
      Serial.println("Not Found");
    }
  }
}

OK blh64,
Sorry for not using code tags. My data file is a list of telephone numbers on SD in the format of
"1234567890 + \r\n". I have 514 records so far.

I am trying to build a telephone spam caller list and when there is a new call, I want to do a lookup of previous callers and see if they have called before. The new caller is placed into a String variable and then compared with the caller list that is in a array "Records array" in memory (for speed).

I see that your code is more dynamic and maybe faster but still does the same thing of loading the list into memory array. I want to compare the "Records array" with the new string. That is what I cannot seem to code right. The code "if(strncmp(Records+x, AC, sizeof(AC)) == 0)" comparison did not work. Can't find the matching string in Records array. I was trying to use only the area code first since it is only three characters. The line above that is commented out, is really what I want to compare.

I tried converting the caller list into two long variables and saving but I did not get that code to work either. The spam caller list is a list from multiple sources and the way I stored on the SD seemed to be OK.

The goal is simply to check a list for a new caller and see if they are on the list but, cannot find a way to do this (many, many hours wasted).

Thanks, joelaw

This program works with the test data

//#include <SD.h>

#define TEST_DATA

#ifdef TEST_DATA
const int MAX_SIZE = 620;
#else
const int MAX_SIZE = 6200;
#endif

char Records[MAX_SIZE];   //String array to hold records
int nbChars;            // file length, <= MAX_SIZE

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial);

#ifdef TEST_DATA

  const char testData[] = "123456789\r\n2532452465\r\n234567890\r\n";
  strcpy(Records, testData);
  nbChars = sizeof(testData);

#else

  Serial.print("Initializing SD card...");
  pinMode(53, OUTPUT);  //DUE pin 53 is chip select

  if (!SD.begin(53))    //DUE pin 53 is chip select
  {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");
  // read all records into memory array "Records"

  File myFile = SD.open("BlkList.log", FILE_READ);
  if (myFile)
  {
    Serial.println("FileName = BlkList.log");
    // read sd data file into Records Array
    nbChars = myFile.size();
    if ( nbChars >= MAX_SIZE ) {
      Serial.println( "File too large" );
      while (1);
    }
    myFile.read( Records, MAX_SIZE);
    myFile.close();
  } else {
    Serial.print("ERROR..... opening BlkList.log");
    while (1);
  }
#endif
  Serial.println("Data loaded");
  findNum();      //function to do lookup for telephone number
}

///////////////////////////////////////////////////
void loop()
{
  // do nothing
}
//////////////////////////////////////////////////

void findNum()    //function to do lookup for telephone number
{
  // test example phone number
  char seek[] = "2532452465\r\n"; //full phone number
  const int nChars = sizeof(seek) - 1;
  //char *AC = "253";    //area code only

  Serial.print("nChars = " ); Serial.println(nChars);
  bool found = false;
  for (int x = 0; x < nbChars; x++)
  {
    if (strncmp(Records + x, seek, nChars) == 0)
    {
      Serial.print("Found : ");
      Serial.print(seek);
      Serial.print( " at position " );
      Serial.println(x);
      found = true;
    }
  }
  if ( !found ) Serial.println("Nothing Found");
}

The only real difference is the length parameter to strncpy() needs to be sizeof(seek)-1

blh64

The code you have does work with the included data. GREAT. But if I change the number to a different one that is on the list it does not find?

First I have to wrap my grey cells around what you have done and then maybe I can find out.

I will post my complete data file. It is about 7k?

Again Thanks for the help.

blh64

The code you have does work with the included data. GREAT. But if I change the number to a different one that is on the list it does not find?

First I have to wrap my grey cells around what you have done and then maybe I can find out.

I will post my complete data file. It is about 7k?

Again Thanks for the help.

BlkList.zip (2.09 KB)

Sure it does. It finds them just fine.

//#include <SD.h>

#define TEST_DATA

#ifdef TEST_DATA
const int MAX_SIZE = 620;
#else
const int MAX_SIZE = 6200;
#endif

char Records[MAX_SIZE];   //String array to hold records
int nbChars;            // file length, <= MAX_SIZE

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial);

#ifdef TEST_DATA

  const char testData[] = "123456789\r\n2532452465\r\n234567890\r\n";
  strcpy(Records, testData);
  nbChars = sizeof(testData);

#else

  Serial.print("Initializing SD card...");
  pinMode(53, OUTPUT);  //DUE pin 53 is chip select

  if (!SD.begin(53))    //DUE pin 53 is chip select
  {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");
  // read all records into memory array "Records"

  File myFile = SD.open("BlkList.log", FILE_READ);
  if (myFile)
  {
    Serial.println("FileName = BlkList.log");
    // read sd data file into Records Array
    nbChars = myFile.size();
    if ( nbChars >= MAX_SIZE ) {
      Serial.println( "File too large" );
      while (1);
    }
    myFile.read( Records, MAX_SIZE);
    myFile.close();
  } else {
    Serial.print("ERROR..... opening BlkList.log");
    while (1);
  }
#endif
  Serial.println("Data loaded");
  findNum( "2532452465\r\n" );
  findNum( "123456789\r\n" );
  findNum( "234567890\r\n" );
}

///////////////////////////////////////////////////
void loop()
{
  // do nothing
}
//////////////////////////////////////////////////

void findNum(const char *seek)    //function to do lookup for telephone number
{
  // test example phone number
  //char seek[] = "2532452465\r\n"; //full phone number
  const int nChars = strlen(seek);
  //char *AC = "253";    //area code only

  Serial.print("nChars = " ); Serial.println(nChars);
  bool found = false;
  for (int x = 0; x < nbChars; x++)
  {
    if (strncmp(Records + x, seek, nChars) == 0)
    {
      Serial.print("Found : ");
      Serial.print(seek);
      Serial.print( " at position " );
      Serial.println(x);
      found = true;
    }
  }
  if ( !found ) Serial.println("Nothing Found");
}

I changed the findnum() to take the string as an agrument and all 3 work just fine.

I don't have as SD shield/card so taking this code and making it work with your data file is a exercise for you.

If your file is really 7k in size, it won't fit into your buffer which is 6200 bytes.

The file is actually 6180 bytes since 12 chars times 515 records = 6180. It will grow.

You are not reading the file on SD into the Records array and then trying to find a 12 char number in that array. You only load the Records with the constant data (testData) which does make three records that can be compared.

What I can't get is how to compare this to a new string read from the incoming caller Id to what is loaded in the Records array. How does "char seek[]" get loaded? your testData is not a changing variable.

Could I read a string (telephone number) into testData and how? The test data in your code is a const not a variable?

Joelaw