How to find a string on text file, and write after a "," comma a value

Hello Everyone, I'm new with Arduino and I need a help with this sketch I'm working...
I'm using a ethernet shield w5100 with SD-Card.
Just for now, I'm working only with SD that I'm writing a text file using the SdFat library.

The point is that I'm able to read the file, find the string and return a "Match" information.
I would like also, after the string I found, write/Replace a value after the "," comma!
Let's supose that I'm lookin for this value: "13110781", on text file will be: "13110781,x" and I would like to write like "13110781,1" or some times "13110781,0".

Follow the code to read and find the value:

// Ported to SdFat from the native Arduino SD library example by Bill Greiman
// On the Ethernet Shield, CS is pin 4. SdFat handles setting SS
const int chipSelect = 4;
/*
 SD card read/write
  
 This example shows how to read and write data to and from an SD card file 	
 The circuit:
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4
 */
#include <SdFat.h>
SdFat sd;
SdFile myFile;

char buf[10];  // Buffer for read the Access file

void setup() {
  Serial.begin(9600);
  // disable w5100 while setting up SD
  pinMode(10,OUTPUT);
  digitalWrite(10,HIGH);
  // Initialize SdFat or print a detailed error message and halt
  // Use half speed like the native library.
  // change to SPI_FULL_SPEED for more performance.
  if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();
  
  // open for read and write
  if (!myFile.open("acesso.txt", O_RDWR)) 
  {        
    sd.errorHalt("opening acesso.txt for read failed");
  }
  // read from the file until there's nothing else in it: 
  int data;
  while ((data = myFile.read(buf,12)) > 0)
  {
    if(strncmp(buf, "13110781", 8) == 0) //Compare the "buf"(SD String) with "result" String to check out if Match!
    {
      Serial.println("Match!");
     // I need to replace the end of "13110781" after the "," with Zero (0) or One (1)
     // I tried the commands bellow... no success...
     // myFile.print(buf[9,10],'0');
     // myFile.write(buf[9,10]'0');
    }
  }
  myFile.close(); 
}

void loop() 
{
  // nothing happens after setup
}

Also follow the text file format:

07836883,x
13108266,x
13033706,x
13056789,x
13035732,x
13110781,x
07901021,x
18430841,x
18427551,x
16029778,x

Thanks in Advance!

 while ((data = myFile.read(buf,12)) > 0)

I can't find any documentation for this use of "read". I would use the documented function:

myFile.readBytesUntil(',', buf, sizeof buf);

hopefully that will leave the file pointer left pointing at the 'x' and then you should be able to:

myFile.write('0');

to overwrite the 'x'.

Hello Mr. johnwasser, thanks for your help!

I check out your code, but it's only recognized by the standard SD library, not for SdFat library...
By the way, I'm not able to make this works on both library...
Could you help me with this ?
Thanks again !

Any more idea ?

Thanks!

Any one could help me with this ?
I'm lost here, and it's appears simple, but I just can't figure out how to do =(

Thanks!

Why are you using SDfat.h when the standard SD library included with the IDE is already based on it?

Hi James, actually I was using the standard SD library, but I see some people saying that SDFat is a quite fast than standard SD library...
For my project I can't see a diference... I just want to make this works fine!

I have tried with both library, but no success yet...
I really appreciate if any one help me with this!

Thanks!

johnwasser:

 while ((data = myFile.read(buf,12)) > 0)

I can't find any documentation for this use of "read". I would use the documented function:

myFile.readBytesUntil(',', buf, sizeof buf);

hopefully that will leave the file pointer left pointing at the 'x' and then you should be able to:

myFile.write('0');

to overwrite the 'x'.

Hi John,

I have tried this

  myFile = SD.open("index5~1.htm");
  
  if (myFile) {
    Serial.println("index5~1.htm:");
    // read from the file until 
    
    myFile.readBytesUntil('Equipment NO-1', buf,sizeof(buf));
    //Serial.println(myFile.write("_XX"));---Want to put data Equipment NO-1_XX in the file
    Serial.println(buf);

    // close the file:
    myFile.close();
  } else {
  	// if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }

and this

  myFile = SD.open("index5~1.htm", FILE_WRITE);
  
  if (myFile) {
    Serial.println("index5~1.htm:");
    // read from the file until 
    
    myFile.readBytesUntil('Equipment NO-1', buf,sizeof(buf));
    //Serial.println(myFile.write("_XX"));---Want to put data Equipment NO-1_XX in the file
    Serial.println(buf);

    // close the file:
    myFile.close();
  } else {
  	// if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }

The first one displays the data until the word "Equipment", but second doesn't display, might be that is why Martin's code isnt working?

Here is the total executed code just in case.
file is like

aaaaaaaaaaaabbbbbbbbbbb
ccccccccEquipment NO-1_mnYYYYYYYY

want it as

aaaaaaaaaaaabbbbbbbbbbb
ccccccccEquipment NO-1_XYYYYYYYYY

#include <SD.h>

File myFile, myxFile;
char buf[1001];

void setup()
{
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial.print("Initializing SD card...");
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin 
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output 
  // or the SD library functions will not work. 
   pinMode(53, OUTPUT);
   
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");  
    
  // re-open the file for reading:
  //myFile = SD.open("index5~1.htm");
  
  //when I comment above and add below, it doesnt display the data----- SO does the "readBytesUntil" work when we set WRITE mode
  myFile = SD.open("index5~1.htm", FILE_WRITE);
  
  if (myFile) {
    Serial.println("index5~1.htm:");
    // read from the file until 
    
    myFile.readBytesUntil('Equipment NO-1', buf,sizeof(buf));
    //Serial.println(myFile.write("_XX"));---Want to put data Equipment NO-1_XX in the file
    Serial.println(buf);

    // close the file:
    myFile.close();
  } else {
  	// if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
  
  
  
  memset(buf,0, sizeof(buf)); // clear the buffer
  
  
  //to check if written fine
    myFile = SD.open("index5~1.htm");
  if (myFile) {
      Serial.println("index5~1.htm:");
      myFile.find("Equipment NO-1");
      myFile.readBytes(buf,9);
      Serial.println(buf);
    // close the file:
      myFile.close();
  } else {
  	// if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
  
  
  
  
  
  
  
}

void loop()
{
	// nothing happens after setup
}

Martin, hope you dont mind me adding my similar query. Thanks for starting this post.

Edit- just observed the full file?(quite a big one) by card reader, the _XX seems to have been written at end of the file. :frowning:

I can do it now, but it has to open file thrice and close thrice, is there a performance issue you see?
Especially when I have to do 24 such replacements(can find 24pos into an array at a go) before I display a html page from my SD?

Please help me optimize.

The stream issue still exists when opened in WRITE-mode, thats the reason for THREE-open.close
proof-
xyz shows= 1024
abc= 43567(end of file position)

  myFile = SD.open("index5~1.htm");
  if (myFile) {
    Serial.println("index5~1.htm:");
    // read from the file until 
    
    myFile.find("Equipment NO-1");
    //Serial.println(myFile.write("_XX"));---Want to put data Equipment NO-1_XX in the file
    xyz=myFile.position();
    Serial.println(xyz);

    // close the file:
    myFile.close();
  } else {
  	// if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
  
  
  
  memset(buf,0, sizeof(buf)); // clear the buffer
  
 myFile = SD.open("index5~1.htm", FILE_WRITE); 
  if (myFile) {
    Serial.println("index5~1.htm:");
    // read from the file until 
     
    myFile.find("Equipment NO-1");
    abc=myFile.position();
    Serial.println(abc);
    myFile.seek(xyz+1);
    myFile.write("_XX");

    // close the file:
    myFile.close();
  } else {
  	// if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
  
    
  //to check if written fine
    myFile = SD.open("index5~1.htm");
  if (myFile) {
      Serial.println("index5~1.htm:");
      myFile.find("Equipment NO-1");
      myFile.readBytes(buf,9);
      Serial.println(buf);
    // close the file:
      myFile.close();
  } else {
  	// if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }

saiko:
Please help me optimize.

The stream issue still exists when opened in WRITE-mode, thats the reason for THREE-open.close
proof-
xyz shows= 1024
abc= 43567(end of file position)

Hi, I just check out your code and I just can't understand why abc goes to the end of file and xyz goes to the right line...
Any one could help us to figure out how to do this on Write process, because It looks like on read process it's accurate!

Thanks!

rmartins:
I just can't understand why abc goes to the end of file and xyz goes to the right line...

When you open an existing file to write more into it the file pointer is positioned to the end of the file so the new data goes AFTER and not ON TOP OF the old data.

See: SD - Arduino Reference

mode (optional): the mode in which to open the file, defaults to FILE_READ - byte. one of:
FILE_READ: open the file for reading, starting at the beginning of the file.
FILE_WRITE: open the file for reading and writing, starting at the end of the file.

Use file.seek(0) to set the position to 0 and your file.find() will start looking from the start of the file.

johnwasser:

rmartins:
I just can't understand why abc goes to the end of file and xyz goes to the right line...

When you open an existing file to write more into it the file pointer is positioned to the end of the file so the new data goes AFTER and not ON TOP OF the old data.

See: SD - Arduino Reference

mode (optional): the mode in which to open the file, defaults to FILE_READ - byte. one of:
FILE_READ: open the file for reading, starting at the beginning of the file.
FILE_WRITE: open the file for reading and writing, starting at the end of the file.

Use file.seek(0) to set the position to 0 and your file.find() will start looking from the start of the file.

SD - Arduino Reference

Thanks John ! That's works fine!
Just one more question... I was looking in the documentation of SD, and I can't find anything about to rename the file.. I know that SDFat lib have this... do you know if it's possible ?
I'm trying to combine this... I check out for the "file.seek" and "file..find" on SDFab, but I can't find anything related...
So, I would like to use the rename and search the string in the text file as fast as possible... what do you recommend ?

Thanks again!

rmartins:
Just one more question... I was looking in the documentation of SD, and I can't find anything about to rename the file.. I know that SDFat lib have this... do you know if it's possible ?

Looks like they left that out. I guess you have to copy the file again to re-name it. :frowning: