Arduino Read Line on SD Card Text File

Hi, can someone can help me with code. This is what I need.
-- I need the Arduino to read the first line on the text file, and separate the first 5 char and last remaining char . ex. I have the first line abcde12345, it would display like this.
user: abcde
pass: 12345

then after reading arduino will delete that first line and will read the next line. and so on and so fort.

In the text file I for example I have saved.
abcde12345
fghij67890
klmno01234
and so on and so fort..

so far I manage to display the first line only.

Thank you, appreciate the help..

What's the problem? Reading the next line? Or splitting username and password?

Why did you choose that format for a line; it would be more flexible if you separated the 'fields' by a comma.

Why do you want to delete lines? Do you want to end with an empty file?

sterretje:
What's the problem? Reading the next line? Or splitting username and password?

Why did you choose that format for a line; it would be more flexible if you separated the 'fields' by a comma.

Why do you want to delete lines? Do you want to end with an empty file?

I only get to read the first line..

I still need
delete what was read..
read the next occurring...(then delete.. so on and so fort)
splitting character

yes I need the file to be emptied and give an error when it becomes empty

Ok , I already fixed the function where I can read the first line and separate character of the first line, any help for deleting the first line code? thank you for any help..

Deleting is done by copying the remainder of the file to a new file, deleting the original file and renaming the new file.

It would be straight forward on a PC, there might be limitations in the SD library (e.g. only open one file at a time, not sure).
According to SD - Arduino Reference you can nowadays open multiple files.

An alternative to deleting the line is by marking it as invalid with a special character (e.g. a question mark or a space as the first character of the user name).

Hi this is the output I get on my terminal.

text file.PNG

terminal.PNG

So?

If you have problems, post your code (between code tags [code] and [/code]), explain what you expect it to do and explain what it does.

And why do you provide screenshots of a text file? And of an application? You can copy the text and paste it here (between code tags [code] and [/code]) as well.

rhatbuh:
Ok , I already fixed the function where I can read the first line and separate character of the first line, any help for deleting the first line code? thank you for any help..

Are you using String variables? Simple char array strings would make this easier.

If you read 1 char at a time from the file

abcde12345
fghij67890
klmno01234
............etc

and put the first 5 chars into a string with a char == 0 (NULL) at the end, it's a printable string that you can operate on a char at a time using array techniques.

char passName[ 6 ], passWord[ 6 ];

So passName becomes an array with 'a','b','c','d','e',0 as the values of the 6 elements and passWord gets the next 5 reads and a 0 terminator. Your code sees the newline char at the end of the line and skips it then you can read and store the next, etc.

As long as you keep reading chars with read() the file pointer will advance 1 at a time. Always check the return, -1 means you ran out.

If you're checking a file for a match to user entries it's even easier.
Put the entered name to check in passName[ ] and set up a byte variable for an index then start reading the file.
Compare the first char in each line to passname[ 0 ] and if it matches then continue trying to match all 5 chars.
If they don't all match, read the rest of the SD line and after the newline char at the end (newline char is '\n') the next line starts and you continue the match routine until you get a match or reach end of file (read returns -1) without a match.
If the name matches then compare the user entered passWord to the next 5 chars in the file. If no match then keep looking and if it matches then there's your proof.

You don't need to use text commands to process text. Often it's quicker not to though you might write more lines of code, might not.

Hi this is the code I have, I wanted to delete the first line after reading it, then when the next run turns, it will read the char from the second line, so on and so fort.

#include <SD.h>
#include <SPI.h>

int CS_PIN = 10;
char logfile[] = {"text.txt"};

File file;

void setup() {

  Serial.begin(9600);
  initializeSD();

  openFile(logfile);
  while(file.available()) {
    // print the lines to serial monitor
    Serial.println(readLineUser());
    Serial.println(readLinePass());
    break;  //stopping reading all the line on file
  }
  closeFile();
}
void loop() {
}

void initializeSD() {
  Serial.println("Initializing SD card...");
  pinMode(CS_PIN, OUTPUT);

  if (SD.begin()) {
    Serial.println("SD card is ready to use.");
  } else {
    Serial.println("SD card initialization failed");
    return;
  }
}

void closeFile() {
  if (file) {
    file.close();
    Serial.println("File closed");
  }
}

int openFile(char filename[]) {
  file = SD.open(filename);
  if (file) {
    Serial.println("File opened with success!");
    return 1;
  } else {
    Serial.println("Error opening file...");
    return 0;
  }
}

String readLineUser() {
  String received = "";  
  char ch;
  while (file.available()) {
    ch = file.read();
    if (ch == ',') {            // Is the tag starting? / as result this is the tag ending
      return String("USER: "+received);  // Return what you have so far (ID)   
    } else if(ch == '\n') {      // Is the tag ending? / as the result this is the tag start
      received = "";            // Empty the string, we don't need br
    } else {                    // Everything's OK, append to the string
      received += ch;
       
    }
  }
  return "";
}   
String readLinePass() {
  String password = "";
  char ch;
  while (file.available()) {
    ch = file.read();
    if (ch == '\n') {            // Is the tag starting? / as result this is the tag ending
      return String("PASSWORD: "+password);  // Return what you have so far (ID)   
    } else if(ch == ',') {      // Is the tag ending? / as the result this is the tag start
      password = "";            // Empty the string, we don't need br
    } else {                    // Everything's OK, append to the string
      password += ch;
      
    }
  }
  return "";
}

this is the output of the code:
Initializing SD card...
SD card is ready to use.
File opened with success!
USER: line
PASSWORD: 12345

File closed

This is whats in the text file:
line,12345
line,23456
line,34567
line,45678
line,56789
line,67890

You do not attempt to delete a line.

And below will cause your while (file.available()) to stop after the first line

    break;  //stopping reading all the line on file

sterretje:
You do not attempt to delete a line.

And below will cause your while (file.available()) to stop after the first line

    break;  //stopping reading all the line on file

Hi, I cant figure out yet how to delete the line that was red.

yes because I just wanted to read only the first line, and then at the next run of the code, it will read only the 2nd line.

rhatbuh:
Hi, I cant figure out yet how to delete the line that was red.

You can't, not directly.

sterretje gave you some options in reply #4.

Another thing you could do is write the number of lines read so far into EEPROM and skip over that many when starting.

rhatbuh:
Hi, I cant figure out yet how to delete the line that was red.

yes because I just wanted to read only the first line, and then at the next run of the code, it will read only the 2nd line.

With SD you could write a new file without that line or you could make a file that the last byte is the number of the last line read, assuming no more than 255 lines with passwords else that file needs to be a growing series of 16 or 32 bit values. Every time you read a name and pw you need to append the line number to the last-line file. When the program starts it needs to open that file and set the seek pointer to the end and read the last line number read to read the next line next time.

With SD you might sort data from a file to write another but never sort the original records in file, it'd use the card up too fast. The thing to do instead is to write a file of sorted offsets into the original data file. The first offset in that file has how far into the original file the 1st sorted word begins. You can link data any way you want, have 20 ways to access and not use 20x the media or make copies.

rhatbuh:
yes because I just wanted to read only the first line, and then at the next run of the code, it will read only the 2nd line.

OK, just wanted to hear that you knew what was happening.

The below is a replacement for your while-loop.

  while (file.available())
  {
    String user = readLineUser();
    String pwd = readLinePass();
    Serial.println(user);
    Serial.println(pwd);

    // if marked as deleted
    if(user[0]=='?')
    {
      // continue for next line
      continue;
    }

    // calculate total number of bytes that were read
    byte length = user.length() + pwd.length() + 1;
    // set file pointer to beginning of line in file
    file.seek(length * -1);
    // indicate record deleted by writing a "?" at first position in line in file
    file.print("?");
    // done
    break;
  }

It marks the line that was read with a '?'; it does not delete the line. The sketch will read lines till it finds a line that does not start with a '?'. For small files that should not be an issue, if you have a few

Code compiles but I can't test.

You need to harden your code a bit more. initializeSD can fail but you have no means to react on it. openFile returns a value but you don't check in setup() to see if it succeeded.

SD does not work enough like magnetic drive to go back into a file and change bytes. It will have to copy the block with the change then link that into the file. SD has a controller that does wear leveling of the flash, every block is mapped and only whole blocks are written though you don't see it. But buck up, you change the buffer and might change it more before it gets sent to the SD card. That's why writing a new file doesn't make 512 progressive copies to write the 1st block, buffer fills then writes.

Are you saying my code will not work? You might be right; I can't test.

sterretje:
OK, just wanted to hear that you knew what was happening.

The below is a replacement for your while-loop.

  while (file.available())

{
    String user = readLineUser();
    String pwd = readLinePass();
    Serial.println(user);
    Serial.println(pwd);

// if marked as deleted
    if(user[0]=='?')
    {
      // continue for next line
      continue;
    }

// calculate total number of bytes that were read
    byte length = user.length() + pwd.length() + 1;
    // set file pointer to beginning of line in file
    file.seek(length * -1);
    // indicate record deleted by writing a "?" at first position in line in file
    file.print("?");
    // done
    break;
  }



It marks the line that was read with a '?'; it does not delete the line. The sketch will read lines till it finds a line that does not start with a '?'. For small files that should not be an issue, if you have a few

Code compiles but I can't test.

You need to harden your code a bit more. *initializeSD* can fail but you have no means to react on it. *openFile* returns a value but you don't check in setup() to see if it succeeded.

Hi @sterretje, thank you for the help.. but I have tested the code it does the same thing as mine, but that is a good start, to mark the line to ignore it from reading.

Hi Everyone thank you for your comments, I brought the code, and its using EEMPROMRead command to do the reading and storing and marking the line, it does not delete the line that was red, it only marked it and added to EEMPROM. That was the Idea I think, my machine is up and working.

Thank you,

Do you mind sharing the code sir?