Lettura file da una sd.

Salve,
l'intenzione è quella di andare a leggere da un file di testo dei caratteri:
la cosa particolare è che non so ( o meglio ho provato ma non riesco) a dire alla funzione file.read quanti caratteri leggere. Mi spiego meglio.

char buffer [17];
if (!sd.begin(SD_CHIP_SELECT_PIN)) {
    sd.initErrorHalt();
  }

  if (!file.open("SoftSPI.txt", O_RDWR | O_CREAT)) {
    sd.errorHalt(F("open failed"));
  }

file.rewind();

while (file.available()) {
    file.read(buffer,17);
  } 

Serial.print(buffer);
[\code]

la cosa strana è che se faccio così buffer in seriale mi mostra caratteri strani tutto tranne quello letto. C'è qualche conversione da fare? interpreto male l'utilizzo di file.read?

Grazie per le eventuali risposte

Stai sempre usando la sdFat o altra libreria? ... perché la sdFat è piena zeppa di esempi, studia quelli !

Guglielmo

si sd fat, specificamente quello sempre inerente al software spi .... quando vado a leggere da file lo legge perfettamente, e ci siamo.

il problema nasce che a me non serve TUTTO il file letto ma solo una parte (17 caratteri) oppure magari finquando legge qualche carattere particolare , / + ? il file lo posso strutturare come voglio.
la domanda è che funziona pure ... ma non posso testarlo

se faccio file.read(buffer, 17) non posso verificare che quello letto è corretto perchè dopo se me lo printo in seriale escono caratteri strani .... non vorrei che tipo devo convertirli ...

L'errore non è nella read(), ma nella print(), che si aspetta in input una stringa standard C, quindi con il terminatore.

Dunque alloca un elemento in più in fondo al tuo buffer e mettici '\0'.

SukkoPera:
Dunque alloca un elemento in più in fondo al tuo buffer e mettici '\0'.

Sai quante voglte glie l'ho detto e ripetuto in suo altro thread ? ? ? :smiling_imp:

Inoltre, la "lettura sino a terminatore di riga '\n' ", sta in uno degli esempi ... ma si fa fatica a leggerli e studiarli ... ::slight_smile:

Guglielmo

for(i=0; i<17; i++){ //in realtà devo leggere 16 caratteri effettivi
       buffer[i]=0;
       }
buffer[i]='/0'; 

//dopodichè faccio

file.read(buffer,17);

Serial.print(buffer);

;

Cosi dovrebbe andare?

Senza fare tutto quel casino:

char buffer[18];
file.read(buffer,17);
buffer[17]='\0';   // NOTA LA DIREZIONE DELLA BARRA! \ non /
Serial.println(buffer);

SukkoPera:
Senza fare tutto quel casino:

char buffer[18];

file.read(buffer,17);
buffer[17]='\0';  // NOTA LA DIREZIONE DELLA BARRA! \ non /
Serial.println(buffer);

grazie sukkopera ^^ stasera provo e vi faccio sapere. Mi confermi che non c'è bisogno di fare alcun tipo di conversione per visualizzarlo in seriale correttamente?

Inoltre ammettiamo che io abbia un file da leggere strutturato in questo modo

E100453401854621E1, PIACENZA
R100453401854624R1, TARANTO
.
.
.
................................, CITTAN

come potrei dire imporre la condizione all'interno della file.read di leggere tipo fino alla virgola?

ma quando si inizializza un stringa tipo:

char buffer[18];

l'ultima posizione, cioè il buffer [17], non dovrebbe già essere messo a '\0'...o dichiarandola come locale non ne ho certezza?

No, le variabili locali non sono mai inizializzate a niente di particolare, solo quelle globali a 0.

SukkoPera:
Senza fare tutto quel casino:

char buffer[18];

file.read(buffer,17);
buffer[17]='\0';  // NOTA LA DIREZIONE DELLA BARRA! \ non /
Serial.println(buffer);

ovviamente funziona. Ora Ammettiamo che io strutturi un file in modo che se questi 16 caratteri letti sono uguali a qualcosa, mi deve stampare sull'lcd LA SECONDA LINEA DEL MIO FILE, poi continuo a leggere il file e passo alla 3 riga dove ci saranno altri 16 caratteri da leggere quindi altro confronto se diverso passo direttamente alla 5 linea .... beh ci siamo capiti credo.
Vorrei usare la funzione seek per spostarmi di linea.... secondo voi può funzionare un'idea del genere?

vi posto la mia idea di file di testo:

12344567891234567
ciao
9876543211234567
sole
......
[\code]

La funzione seek() va bene solo se sai ESATTAMENTE dove posizionarti, ovvero se il file è strutturato in "records" di lunghezza fissa tutti uguali in modo che la posizione è data dal ((numero_record -1) * (lunghezza_record)).

Se i "records" NON sono tutti uguali non la puoi usare.

Guglielmo

gpb01:
La funzione seek() va bene solo se sai ESATTAMENTE dove posizionarti, ovvero se il file è strutturato in "records" di lunghezza fissa tutti uguali in modo che la posizione è data dal ((numero_record -1) * (lunghezza_record)).

Se i "records" NON sono tutti uguali non la puoi usare.

Guglielmo

e come posso fare per 'muovermi' all'interno del file? non posso tipo immaginare di vedere il file come una sorta di matrice? in questo modo con i 2 indici (riga e colonna) posso decidere cosa mi serve, cosa stampare ...
stavo tentando di utilizzare int n=file.position() ma mi da errore (has no member named ... )
dove posso andare a leggere esempi di programmazione? tipo non riesco a trovare l'esempio dove legge fino a fine linea ... sarebbe gia un bel passo avanti

#define MAX_LINEA 80

File fp = SD.open ("antani.txt", FILE_READ);
if (fp) {
  char linea[MAX_LINEA], c;
  byte len = 0;
  while (fp.available ()) {
    if ((c = fp.read ()) != '\n' && len < MAX_LINEA - 1) {
      linea[len++] = c;
    } else if (len > 0) {
      linea[len] = '\0';
      // A questo punto fai quel che vuoi con "linea"

      len = 0;  // Pronti per la prossima linea
    }
  }
  fp.close ();
}

(Sono andato a memoria, correggi tu eventuali errori.)

... ho ripulito il thread di commenti, battute e quant'altro ... continuiamo la discussione tecnica.

Guglielmo

Per leggere fino a qualcosa io ti consiglio
A) metti quei qualcosa a distanze fisse e leggi con la read a due argomenti come ti é stato mostrato
B) inizializza una stringa di dimensioni ampiamente sufficienti, e riempila elemento per elemento con la read normale in una for. Sappi che la condizione della for é su una funzione e non sulla variabile di for, e che esiste la funzione file.pick () (o nome simile) che legge un carattere senza portare avanyi il puntatore. A te capire la condizione
C)NON so se esiste una "readuntil()" o qualcosa di simile.

Buongiorno a tutti: Ho provato ad implementare i CONSIGLI che mi hanno dato gli utenti e ho provato a scrivere questa sorta di controllo per muovermi nel file di testo.

Ho deciso di utilizzare righe di lunghezza fissa 50 e quindi di strutturare il file in questo modo:

ABCDE123456789FGH,PIACENZA
ABCDE123456789FGH,ROMA

precisazione: la virgola nel file, su ogni riga, verrà inserita esattamente dopo 16 caratteri quindi sarà FISSA.

l'idea del programma è di leggere i primi 16 caratteri, metterli in una array di char, fare il confronto con un altro array di char; a questo punto se ad esempio c'è match con la prima linea, il programma dovrebbe stamparmi PIACENZA, altrimenti andare avanti.

per quanto riguarda il codice avrei pensato di muovermi all'interno del file in questo modo:

char c, riga[massimo], riga2[massimo];
byte len=0;
int indice =0;

SdFile file;

if (!file.open("dancexfect1.txt", O_RDWR | O_CREAT)) {
   sd.errorHalt(F("open failed"));
   while(file.available()){
           c=file.read();
          if(c!=',' && len<massimo-1){
            riga[len++]=c;
            }
          if(strcmp(linea,barcode)==0 && c!='\n'){
            riga2[len++]=c
            indice++;
            }
    len=0;
    }
}
if (indice!=0)
Serial.print(riga2);
else
Serial.print("barcode non trovato2);

chiedo scusa per eventuali errori. Secondo voi potrebbe andare?

Ma non hai guardato gli esempi della libreria ... altrimenti avresti visto che c'è un metodo getline() che legge riga a riga usando il delimitatore di riga che vuoi tu (normalmente '\n').

Se vai nella cartella extras che si trova nella cartella SdFat e apri index.html hai accesso alla documentazione di tutte le classi, metodi, variabili, ecc.

Guglielmo

gpb01:
Ma non hai guardato gli esempi della libreria ... altrimenti avresti visto che c'è un metodo getline() che legge riga a riga usando il delimitatore di riga che vuoi tu (normalmente '\n').

Se vai nella cartella extras che si trova nella cartella SdFat e apri index.html hai accesso alla documentazione di tutte le classi, metodi, variabili, ecc.

Guglielmo

sarebbe credo perfetta ma bisogna sempre implementarla con la software spi..... ho pensato però di prendere arduino leonardo ethernet con a bordo una bella (ma soprattutto solo) sd e PROVARE. voglio capire come funziona getline, magari anche fgets e capire se fanno al caso mio.
Ad occhio e croce, domanda anche valida per gli altri ovviamente, il mio codice potrebbe andare bene o necessita di qualche altra modifica?

... guarda che la SoftwareSPI dovrebbe essere trasparente ... basta abilitarla con il #define che hai già visto con l'esempio e una riga in più per configurarla !!!

Guglielmo