Compound questions. readStringUntil, and String vs array

I need some help with a couple issues (which are related I think)
I'm very very new here, so let me know if I have breaches in etiquette please.

Part 1)
I have a data file I want to turn into variables to use.
The data file looks like
2
3
44
120

etc.

I use
oneLine = myFile.readStringUntil("\n");
and
nailNum = oneLine.toInt();
but when I dump that to see, I get just the first variable, and no others.

Can anyone tell me what I'm doing wrong. I've been reading like crazy to understand but, well, fail.

Part 2.
Related to that variable input technique, is that I am using strings instead of arrays.
I remember reading in a forum discussion that for the life of me I cannot find again, that using arrays is a better idea, and using atoi() instead of toInt().
I think the reasoning being it used a lot less memory, which is now an issue for me.

But I am struggling with that also.

Can someone elaborate on array virtues as well as how to use them to import an integer from a list in a text file on the SD card?

The posting would be handy as it also had the support code which I need, such as how to read an entire line from some flavor of file related read.

Thanks so much.

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

File myFile;
String oneLine = String();
//int lineNum = 1;
int nailNum = 0;  //Valid 0 - 240, larger or smaller causes while(1)


void setup() {

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
  }
  Serial.println("Initializing SD card");
  if (!SD.begin(10)) {
    Serial.println("initialization FAIL. Self destruct sequence in 10...9..");
    while (1)
      ;
  }

  Serial.println("initialization WORKED. Amazing.");
  // open the file for reading:

  myFile = SD.open("test1.txt", FILE_READ);  //so here is myFile, which is test1.txt
}



/* while(dataFile.available())
    { 
     arrayOfChars[i] = dataFile.readStringUntil('\n'); // Read the charcters until you get a new string
     i++;
    }
*/




void loop() {  // get each line, turn into a variable, print variable

  if (myFile) {  //make sure the file is there and can be opened
    Serial.println("Now reading from file. Yay. ");
  } else {  //otherwise print fail and infinite loop
    Serial.println("Can't seem to find file.....");
    while (1)
      ;
  }

  myFile = SD.open("test1.txt", FILE_READ);

  while (myFile.available()) {  //read from myFile until the end
    oneLine = myFile.readStringUntil("\n");
    Serial.println("string found. Digesting line number  ");
    //Serial.println(lineNum);    // just so I have some idea how it's progressing
    //lineNum += 1;

    nailNum = oneLine.toInt();
    if ((nailNum >= 240) || (nailNum < 0)) {  //nailNum has be be valid,
      Serial.println("Number found out of range or invalid, or end of file");
      while (1)
        ;
    }
    Serial.println(nailNum);
  }
}

Here's some help:
Forum guidelines

your file is getting opened in the setup, you don't need to open it again in the loop and you print only outside the while loop

try this

#include <SD.h>
File myFile;

void setup() {
  Serial.begin(115200);
  while (!Serial) ;

  Serial.println(F("Initializing SD card"));
  if (!SD.begin(10)) {
    Serial.println(F("initialization FAILED. Self destruct sequence in 10...9.."));
    while (true);
  }

  Serial.println(F("SD initialization WORKED. Amazing."));

  myFile = SD.open("test1.txt", FILE_READ);  //so here is myFile, which is test1.txt
  if (!myFile) {
    Serial.println(F("File access FAILED. Self destruct sequence in 10...9.."));
    while (true);
  }

  Serial.println(F("FILE access WORKED. Amazing."));

  while (myFile.available()) {  //read from myFile until the end
    String oneLine = myFile.readStringUntil('\n');
    long nailNum = oneLine.toInt();
    if ((nailNum >= 240) || (nailNum < 0)) {  //nailNum has be be valid,
      myFile.close();
      Serial.println(F("Number found out of range or invalid"));
      while (true);
    } else {
      Serial.println(nailNum);
    }
  }
  myFile.close();
}

void loop() {}

(typed here, untested)

readStringUntil() takes a char not a string. You are reading the entire file on the first read and then toInt() is parsing it and only converts the first line. To verify this, try printing out your onLine variable.

oneLine = myFile.readStringUntil('\n');

good catch !

Hey, thanks so much for the help.

Okay, now I have even more questions (and some comments)

So:
Thanks for the pickup of opening the file twice, fixed.

AND
it looked like the Serial.print was outside the while loop, only because i copied the file on character short. oops, and sorry. I misled you with that.

AND
I ran your code and for output in monitor got: 5 question marks inside a black circles and "I", another question mark, and an "r" as an output.
That was all. So that doesn't seem to work.

AND
I see a
Serial.println(F("Initializing SD card"));
What is the F doing in there? I don't see anything in the println doc about that.

set the serial monitor to 115200 bauds, not 9600 (bottom right corner of the window)

the macro F("xxx") puts the string "xxx" in flash memory to save SRAM. it's well hidden in the doc, you have to go look at the end of PROGMEM

The F() macro

When an instruction like :

Serial.print("Write something on  the Serial Monitor");

is used, the string to be printed is normally saved in RAM. If your sketch prints a lot of stuff on the Serial Monitor, you can easily fill the RAM. If you have free FLASH memory space, you can easily indicate that the string must be saved in FLASH using the syntax:

Serial.print(F("Write something on the Serial Monitor that is stored in FLASH"));

use '/n', not "/n". The first is a character, the second is a string. By the way, should that be \n? It is, in your code. Please be precise when communicating, it really helps...

arghhhh

actually it's '\n' for the line feed, not '/n'

I corrected my previous code

All the code above has \n, but @r44chopper introduced the /n which I was correcting as I answered his question. We posted sort-of-simultaneously, as though you posted 7 minutes ahead of me per forum timestamps, your post didn't appear here until I'd replied.

I edited my code from post #3 to include the '\n' instead of the "/n"

so code in #3 should be tested

1 Like

yep, back-editing has a way of really complicating these forum postings. Would be nice if there was some form of markup hilighting, so it would be obvious; the 'edited counter' is something I miss often. Oh well.

there is the little orange pencil above the post when it has been edited and a number (the number of edits).

if you click on that you can see the history

(I also mentioned in post 11 that I did the modification)

1 Like

I see. I didn't know I had to adjust that. Thanks so much!

And thanks for that too. Such great tips and information.

But most of all:
Thanks the the code you provided above.
Not only do I now understand it (mostly), but it works as you said.
I now have int values I can mess with!

Which brings us to part B of my original post (I won't make part B in the future...)
Is String more memory intensive than array[]?
Should I be reading into an array and using atoi()?
The problem is both of our codes use about 35% of available, and I have a long way to go. I need to start being frugal with space.
I have a stepper and servo to control after getting the data (you solved)

Should I post a completely new topic on this instead of hoping this will get answered whilst piggy backing on

Thanks again for all your efforts!!

yes String requires more flash to start with and a bit more memory for each string.

It can also lead to memory issues if you don't understand what you are doing in terms of dynamic memory allocation.

that's the price to pay to not worry about the length of the buffer and not learning cStrings functions.

I would recommend to study cStrings (null terminated char arrays) and know about those functions in stdlib.h and string.h . There is a learning curve, but it's good information to know. Just be very diligent when you store stuff in cString to not overflow the array

Strongly recommend as well. It also 'peels back the curtain', allowing you to learn a bit more about memory management, arrays, and pointers. It's all good to know when dealing with small processors and limited memory.

Thanks for the pointer. I know I am extremely new at all this, and have a lot to learn, so help is so very appreciated from everyone.
I'll get to reading!

Addendum:

I found a solution to Part B of this topic.
An Arduino Max from Amazon for $20.
8 Times the memory, is more than I will every need in the short remainder of my days.

Thanks again for all of the great suggestions, and am very grateful!
Cheers

do you have a link to this "Arduino Max"?

exotic platform are not well supported, if I need more memory I would use a MKR or ESP32
(the ESP32 would probably be way cheaper than $20)

Thanks, for that, never occurred to me to click on the markup indicator. Sigh. That will be useful going forward!