how to overwrite the data in SD card?

i am sending messages over serial and want to save received messages and sent messages in SD card. i am successful so far as the sent messages are saved in sent text file and received messages are saved in recv text file.
the problem here is, when so ever i read those messages from SD card using " lcd.write(myFile.read());" command, i want it show only the current sent or received message and either remove or overwrite all others messages in it.
help

thank you :slight_smile:

If you only want the last message, is there any reason it has to be saved to a file? Seems like it would be easier and more efficient to just keep it in a variable?

If it absolutely must go in a file, you could close and reopen the file, then write the new message: immediately writing after an open should overwrite the old contents. You may also be able to use seek() to set the file position back to the beginning before writing the next message.

Can you explain exactly what you're trying to accomplish by only keeping the last message in the file? There may be a better way to do it.

yeah sure sir :slight_smile:
i am building a chat server actually. since i am not that much expert in programming so thats y i was interested in keeping the last message only !
say if two people are communicating , i want their messages to be stored in a file! i have created a text file for received messages and a separate one for sent messages! it would be even more better if all the messages will be stored in an good alignment but i was not successful in doing so, hence i thought to just store the current received and sent message only!!
Also i looked for seek() command but was unable to use it in my coding as i did not understand that how to use it correctly??
any help sir?? :slight_smile:

Take the big hammer to it:

You can delete a file by calling SD.remove("unwanted.txt") - be careful! This will really delete it, and there's no 'trash can' to pull it out of.

Then open a new file with the same (or different) name.

SD tutorial.

It would be helpful if you posted your code so far. Be sure to use code tags (use the formatting icon that looks like a scroll with blue angle brackets.)

I’m thinking you want to do two unrelated things: store a log of the entire conversation to SD card, and display the last message on an LCD display. Perhaps forcing the SD card file to do both isn’t the way to go? It seems to me that when you get a message, it should be displayed directly on the LCD, before it even goes to the SD card. That way you don’t have to worry about the file only holding the last message, because you won’t be reading it back to display it. I think you’re trying to force the SD card file to do two incompatible things. Consider other ways to do it. Let us see your code so far, and we’ll be able to make suggestions.

here is my code:
i have develop a menu. by pressing the key 2 from the keyboard, we enter in the Create message window, where we can type a message and after pressing enter key it is to be transmitted to the receiver end! now i want my sent messages to be stored in a sent.txt file and the received messages to be stored in a recv.txt file!!

#include <PS2Keyboard.h>
#include <LiquidCrystalFast.h>
#include <SPI.h>
#include <SD.h>
File myFile2;
File myFile;
LiquidCrystalFast lcd(13, 9, 22, 23, 5, 6);

#define SOP '<'
#define MOP '#'
#define EOP '>'
#define id "Suraj"
boolean started = false;
boolean ended = false;
boolean hope = false;

char inData[80];
byte index;
const int DataPin = 4;
const int IRQpin =  3;
byte menu=0;
PS2Keyboard keyboard;
String kbdata="<#";
const int chipSelect = 10;
void main_menu()
{
   lcd.setCursor(0,0);
   lcd.print("1.Inbox  2.Create");
   lcd.setCursor(0,1);
   lcd.print("3.Outbox 4.Users");
}
void read_file()
{
  lcd.clear();
  while (myFile.available())
  {
        lcd.write(myFile.read());
  }
   lcd.clear();
   delay(2000);
   SD.remove("recv.txt");  
  }
  
  void read_file2()
{
  lcd.clear();
  while (myFile2.available())
      {
        lcd.write(myFile2.read());
        }
       
   
 delay(2000);
 SD.remove("sent.txt"); 
  }

void setup(){
  Serial.begin(9600);
  Serial1.begin(9600);
   pinMode(13, OUTPUT);
   lcd.begin(20,4);
   lcd.setCursor(0,0);
   lcd.print("Welcome to our FYP :)");
   delay(2000);
   main_menu();  
   //delay(1000);
  keyboard.begin(DataPin, IRQpin);
  //Serial.begin(9600);
  Serial.println("Keyboard Test:");

 if (!SD.begin(chipSelect)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
/*
menu=0    main menu
menu=1    inbox
menu=2    new
menu=3    outbox
menu=4    Online Users
*/ 
menu=0;
}      

  void loop(){
    if (keyboard.available()) {
    // read the key
    char key = keyboard.read();
    if ((key) && (menu==0))
       {
        char a = key;
        lcd.clear();
        lcd.cursor();
        //Create Message
        if (a=='2')
           {
            lcd.setCursor(0,0);
            lcd.print("Create new message");
            menu=5;
            delay(400);
            lcd.clear();
            }
       
        //Inbox
       else if(a=='1')
        {
           // Inbox
           lcd.clear();
           //lcd.print("inbox");
           menu=1;
           myFile = SD.open("recv.txt");
        if (myFile) 
        {
          lcd.setCursor(0,0);
          lcd.println("1 New Message");
        }
        }
      
       //Outbox
       else if (a=='3')
        {
          lcd.clear();
          //lcd.print("Outbox");
          //delay(400);
          lcd.clear();
          menu=3;
          
          myFile2 = SD.open("sent.txt");
  if (myFile2) {
   
    // read from the file until there's nothing else in it:
        lcd.setCursor(0,0);
        lcd.println("Current Sent msg");
        }
       }
        
        //Draft
       else if (a=='4')
        {
          lcd.setCursor(0,0);
          lcd.print("Checking Online users");
          delay(400);
          lcd.clear();
          menu=4;
          Serial1.print("<");
          Serial1.print("#");
          Serial1.write(0x7F);       //checking if any 1 is available
          Serial1.print(">");
          lcd.println("request sent");
          delay(400);
          lcd.clear();
        }
        
        else
        {
          lcd.clear();
          lcd.setCursor(0,0);
          lcd.print("Press valid key");
          delay(500);
          main_menu();
        }
       }
        
  
        // Return Key    
        if((key) && (menu !=0))
        {
          char a=key;
          if(a=='*')
          {
            menu=0;
            lcd.clear();
            main_menu();
          }
        }
        
        //Message Open Key
       if ((key) && (menu==1))
       {
         char a=key;
         if (a==PS2_ESC)
         {
           read_file();
         }
       else
     {  
       if ((key !='*') && (key != PS2_ESC))
       {
         lcd.clear();
         lcd.setCursor(0,0);
         lcd.println("Press ESC to read");
         
         lcd.setCursor(10,1);
         lcd.println("OR");
         lcd.print("* to go back");
     }
     }
       }
       
       
       
       
    //Message Open Key
       if ((key) && (menu==3))
       {
         char a=key;
         if (a==PS2_ESC)
         {
           read_file2();
         }
          else
     {  
       if ((key !='*') && (key != PS2_ESC))
       {
         lcd.clear();
         lcd.setCursor(0,0);
         lcd.println("Press ESC to read");
         lcd.setCursor(10,1);
         lcd.println("OR");
         
         lcd.print("* to go back");
     }
     }
       }
       if ((key) && (menu==4))
       {
         char a=key;
         if (a==PS2_ESC)
         {
           
           lcd.clear();
           lcd.setCursor(0,0);
           lcd.print("Create message");
           delay(1000);
           lcd.clear();
           menu=2;
         }
       }
  
//writing a message
if ((key!='2') && (menu==5) )
  {
    lcd.cursor();
  lcd.print(key);
  Serial.print(key);
kbdata.concat(key);
if (key == PS2_ENTER)
{   
    kbdata.concat('>');
    Serial1.print(kbdata);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Msg Sent");
    myFile2 = SD.open("sent.txt", FILE_WRITE);
  
  // if the file opened okay, write to it:
  if (myFile2) {
   
    myFile2.println(kbdata);
	// close the file:
    myFile2.close();
 
  }
    
    delay(400);
    kbdata="<#";
    menu=0;
    main_menu();
}
}
}

It's a bit hard to follow the logic, and I didn't fully study the code. But I see a few things that might be an issue.

myFile: You open this file every time menu 1 is entered, and you read from it after an escape is typed. But you never close the file, nor do you ever write to it.

myFile2: You open this file every time menu 3 is entered, then you have a comment to read it until there's nothing left, but you don't actually read anything. Then if escape is typed, you call read_file2() to copy everything from the file to the LCD. Then you delay. Finally, you remove the file, but you haven't closed the file. I don't know how happy the library is going to be attempting to delete an open file out from under itself. Then, when you've sent a message, you once again open the file, write the string, and finally close the file.

With myFile, you are constantly reopening the file, but never writing to it, nor closing it.

With myFile2, you are properly closing the file after writing it, but you aren't closing it after reading it and before deleting it.

In addition, your code flow is quite convoluted and hard to follow. It looks like you started out by trying a bunch of different things, adding little bits here and there to add new functionality. It's very easy to get lost working that way.

My recommendation is to use this code as a good learning experience. You now have a pretty good idea of what you want to do. Take the time to organize your thoughts, and write down a concise description of what you want it to do. Don't worry about HOW to do it, just clearly state WHAT it should do, For example: "display the last sent message on the screen" not "read an SD file and copy it to the display."

If you do that, and think about what you want it to do, you should be able to come up with a clearer organization. You will also be able to determine the best way to do things. For example, your previously stated goals of saving all of the messages to an SD card file, and also saving only the last message to the SD card file are mutually exclusive.

Writing to an SD card is good for long term storage (logging ALL messages) it is not good for short term storage (remembering the last written message so it can be displayed.) A variable in RAM is much better for the latter. Trying to make the file do both things is an exercise in frustration. You are currently using kbdata to temporarily hold the message that is being created. That's a good use of a variable. You then write it out to the file, and reset kbdata in preparation for the next message. At that point, it would make sense to copy the contents of kbdata to a new variable (something like lastSentMessage) before you reset kbdata. That way, when it comes time to display the last sent message, you can just write the lastSentMessage string to the LCD without having to call read_file2 and extract it from the SD card. You would already have it in memory. This would get rid of a lot of open/close calls, and eliminate the need to keep deleting the SD card file.

Given what you've said in the past, it seems a more logical way to handle the data would be:

  • Open a single SD file in setup()
  • every time you send or receive a message, write the message to the SD card with a prefix like "S:" for a sent message, and "R:" for a received message. Do this with a function that takes the prefix and the message as arguments.
  • When you create a message, save a copy of it in a variable for easy display. Overwrite that saved value with the new value the next time you create a new message.
  • When you receive a message, save a copy of it in another variable for easy display. Overwrite that one as well when a new message comes in.
  • When it's time to display a message, just use the last value from one of those saved variables, rather than go to the SD card.
  • Strive to make it more modular. Make functions for each menu mode. Then, when you decode a menu key press, cal the function for that menu item. It will make your loop() function much easier to read.

The second time you are typing a very similar sequence of code, consider putting it in a function. The third time you are typing the same sequence of code, it definitely should be in a function.