Hallochen.
Sitze mal wieder ein bisschen am Monstertruck und......kämpfe.
Ich möchte in einem bestimmten Verzeichnis der SD-Karte sämtliche enthaltenen Dateien der Reihe nach öffnen, die erste Zeile einlesen und als Klartext ausgeben.
Wie ich das einlesen mache, hab ich schon mal erarbeitet- der Teil klappt.
Es klappt auch, die Dateinamen im Verzeichnis einzulesen aber ich kriegs nicht gebacken, die jeweilige Datei gleichzeitig zu öffnen.
Serial.println(entry.name());//bis hierher klappts hier wird der Dateiname richtig ausgegeben aber
File routenDatei=SD.open(entry.name());//klappt nicht
Serial.print("geoeffnet: ");
Serial.println(routenDatei); // das wird zwar ausgegeben, enthält aber nur ne "0);
Was hab ich da wieder vermurkst?
Basis ist die Standard-SD-Lib, und das abgewandelte Beispiel 'listfiles'.
gibt vollkommen richtig sowas aus:
ROUTE2.GPS
das ist der korrekte Dateiname- und genau den will ich benutzen, um diese Datei auch zu öffnen (um eben jene erste Zeile zu lesen).
Ich habe die normale SD Klasse noch mit Verzeichnissen genutzt, aber so wie sich das liest reicht das eventuell nicht wenn die Datei in einem Verzeichnis steht.
Um Dateien der Reihe nach zu öffnen gibt es wie in dem Beispiel steht auch openNextFile()
gibt vollkommen richtig sowas aus:
ROUTE2.GPS
das ist der korrekte Dateiname- und genau den will ich benutzen, um diese Datei auch zu öffnen (um eben jene erste Zeile zu lesen).
Du müsstest aber trotzdem die Verzeichnisstruktur und ggf. vorhandene Unterverzeichnisse beachten.
Ist es denn ein Dateisystem mit Unterverzeichnissen?
Oder liegen alle Dateien im Rootverzeichnis und es gibt gar keine Unterverzeichnisse?
Ja-und nein.
Es gibt ein eigenes Unterverzeichnis für die Routen-Dateien, klar.
Das wird aber bereits vorher eingestellt- denn die Dateinamen werden ja völlig korrekt gelesen und angezeigt.
für den Moment habe ich das Problem mehr oder weniger umschifft, indem ichs einfach so mache:
void printDirectory(File dir, int numTabs) // ********** Routendateien zählen ********
{
while(true)
{
File entry = dir.openNextFile();
if (! entry)
{
dir.rewindDirectory();
break;
}
for (uint8_t i=0; i<numTabs; i++)
{
Serial.print('\t');
}
entry.readBytesUntil('#',name,15); //Ersten String lesen, der den Namen enthält
Serial.print("Routenname: "); //String ausgeben
Serial.println(name);
entry.close();
}
}
Funktioniert einwandfrei- es wird da sehr schön ein Teil der ersten Textzeile in der jeweiligen Datei ausgegeben.
Wie man sieht: auch hier kein Unterverzeichnis (da das schon in der setup() ausgewählt wird).
Ob ich das so lassen kann, weiss ich noch nicht, da hier (in dem Beispiel) nur die jeweilige Datei erstmal auf dem display ausgegeben werden soll (drum auch die Verrenkung mit der Inhaltszeile, da die Namen weniger Zeichen hergeben), und man hier dann auswählt, welche Route(ndatei) nachher genommen werden soll.
So- das Problem hat mich eingeholt.
Hatte ich bereits befürchtet...vermutlich blick ich mal wieder irgendwas mit Variablen nicht.
Es geht darum: ich kann durch die Dateien (alle im selben Ordner) nach belieben brausen- das funktioniert.
void printRoutenInfo(File dir) // ********** Routeninfo lesen und ausgeben ********
{
if(routeSelect==1)
{
File routenDatei = dir.openNextFile();
if (! routenDatei) //wenn am Ende angekommen
{
dir.rewindDirectory();//zurück zum Anfang
}
routenDatei.readBytesUntil('#',name,15); //Ersten String lesen, der den Namen enthält
lcd.setCursor(0,1);
lcd.print(name);//Routenname ausgeben
routenDatei.close();
delay(500);
}
}
Das Ganze wird in ner zeitgesteuertem Schleife über den Joystick gemacht: wird der Stick eine gewisse Zeitlang nicht bewegt, dann wird abgebrochen, wird er bewegt, wird die obige Routine erneut aufgerufen und somit die nächste Datei geöffnet.
Das klappt einwandfrei bis dahin.
Nun aber brauche ich eine Möglichkeit, den Namen der aktuellen Datei in einer Variablen zu speichern.
Also: nicht den Routennamen (der IN der Datei steht), sondern nur den Dateinamen, da ich die ausgewähte Datei ja später weiter verarbeiten muss.
Wenn ich nun folgendes mache:
lcd.print('routenDatei');
Wird, anstelle des Dateinamens: 25691 ausgegeben.
lcd.print(routenDatei); das ergibt einfach nur ne 0...
lcd.print("routenDatei");, dann nämlich stünde routenDatei aufm Display, ich brauche den INHALT der (wasauchimmerfüreiner) Variabe routenDatei.
Das Problem scheint daher zu rühren, dass ich in diesem Moment die Datei File routenDatei() bereits wieder geschlossen habe- das muss sein, aber ich muss eben diesen Namen irgendwie speichern...
Ich habe ein Verzeichnis, dessen Name feststeht.
Und ich habe eine Datei, die verschieden heissen kann.
Der Name der Datei ist in ner Variable dateiName gespeichert.
Nun müsste ich sowas haben wie:
File myFile = SD.open("verzeichnis"+dateiName);// Datei liegt im verzeichnis:/Routen
So funktionierts natürlich nicht.
Praktisch müssen "verzeichnis" und dateiName aneinander gehängt werden.
benutze.
Das klappt auch ganz problemlos nur ist es ja denkbar, dass ich dabei die Datei, die ich wollte, überblättere, somit muss das Ganze als Schleife laufen.
Daher hab ich das Ende des Verzeichnisses so abgefangen:
if (! routenDatei) //wenn am Ende angekommen
{
dir.rewindDirectory();//zurück zum Anfang
routenDatei=dir.openNextFile(); // und direkt die erste Datei öffnen
}
Das aber funktioniert-nicht.
Zwar wird hier eine Datei geöffnet, aber irgendwie Mist gelesen.
Lasse ich die zweite Zeile weg, (so hatte ich es bisher), dann wird zwar das Verzeichnis, aber keine Datei gelesen-und auch da kommt natürlich Murks raus.
Hier mal der entsprechende Code im Ganzen:
void printRoutenInfo(File dir) // ********** Routeninfo lesen und ausgeben ********
{
if(routeSelect==1) // der Stick wurde bewegt
{
routenDatei = dir.openNextFile(); //nächste Datei öffnen
if (! routenDatei) //wenn am Ende angekommen
{
dir.rewindDirectory();//zurück zum Anfang
}
routenDatei.readBytesUntil('#',name,15); //Ersten String lesen, der den Namen enthält
lcd.setCursor(0,1);
lcd.print(name);//Routenname ausgeben
routenDatei.close();
delay(200);
}
strcpy(dateiName, routenDatei.name());// ausgewählte Datei speichern
}
Ich muss diesen Wechsel (vom Ende des Verzeichnisses zum Anfang) irgendwie so abfangen, dass entweder die letzte, oder aber wieder die erste Datei sofort geöffnet wird. Jemand eine Idee dazu?
Sodele.
Das Problem ist gelöst.
Wo lag der Fehler? Wie meistens: nen halben Meter vorm Bildschirm.
Nein, ihr könnt ihn in den Programmschnipseln da nicht finden, denn der ist nicht dort (allenfalls ein winziger Hinweis auf den möglichen Fehler).
Also was war es?
Die Routendatei selbst!
Das lesen der Routen funktioniert nämlich so:
zuerst wird der "Header" gelesen, mittels routenDatei.readBytesUntil('#',name,15); //Ersten String lesen, der den Namen enthält
Im Klartext bedeutet das, dass dieser Header nix anderes als ein String ist, an dem ich den Namen der Route erkenne.
Später werden dann die Wegpunkte einzeln eingelesen, schön nummeriert, und zwar so:
wegPunkt = routenDatei.parseInt(); //WegPunkt-Nr. zuerst (Zeilenanfang)
long lat = routenDatei.parseInt();// als zweites kommt lat
long lon = routenDatei.parseInt();// dann lon
sollBreite=lat;
sollLaenge=lon;
if(wegPunkt==wegPunktAktuell)
Das Ganze jeweils so lange, bis aus der Datei nichts mehr kommt.
Wie man sieht, gibts jeweils drei Zahlen: Wegpunktnummer, Länge und Breite.
ABER es wird NUR einfach nach Zahlen "gesucht".
Wenn jetzt ein besonders cleverer Programmieranfänger in den Dateiheader als Routenname beispielsweise schreibt:
"ParkplatzRunde1" dann---genau. Wird die 1 schon als Zahl genommen, alles verschiebt sich um eine Stelle und es kommt unglaublicher Murks raus.
Keine Ahnung, woher ich die plötzliche Eingebung hatte, mir die Routendateien noch mal genauer anzusehen aber sie kam, ich tat es und da ging das Licht auf.
Langer Rede kurzer Sinn: der Routenparser läuft nun fehlerfrei (bis auf eventuelle Bugs, die ich noch nicht bemerkt habe).