Попытка прочитать случайную строку с SD-карты

Мне интересно, знает ли кто-нибудь, как читать случайную строку из файла с именем «PhraseList.csv» или «PhraseList.xlsx» (что проще)? Есть список из 10 тысяч.

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

File myFile;

void setup()
{

 // Открытие последовательной связи и ожидание открытия порта:
  Serial.begin(9600);
   while (!Serial) {
    ; // ждем подключения последовательного порта. Требуется только для Леонардо.
  }


  Serial.print("Initializing SD card...");

  if (!SD.begin(chipSelect)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

  // повторно открываем файл для чтения:
  myFile = SD.open("PhraseList.xlsx");
  if (myFile) {
    Serial.println("PhraseList.xlsx":);

    // читаем из файла, пока в нем ничего не останется:
    while (myFile.available()) {
        Serial.write(myFile.read());
    }
    // закрываем файл:
    myFile.close();
  } else {
    // если файл не открылся, выводим ошибку:
    Serial.println("error opening Phrase List");
  }
}

void loop()
{
    // после установки ничего не происходит
}

, 👍-1

Обсуждение

https://www.arduino.cc/reference/en/language/functions/random-numbers/random/, @Juraj

что такое «случайная строка»? ......... Что это значит? Есть список из 10 тыс., @jsotola

вы хотите прочитать файл xlsx?, @Juraj


1 ответ


1

Чтение отдельной строки из списка в файле — непростая операция. Ну, это "просто", но требует много работы.

Невозможно сказать «Получите мне строку номер 2984 из файла» с помощью обычного текстового файла. Вместо этого вам придется получать каждую строку по очереди, отбрасывая ненужные, пока не дойдете до строки 2984.

Лучшим способом было бы создать собственный «индексированный» формат файла со структурой заголовка файла, описывающей остальную часть файла. Эта структура заголовка будет содержать (помимо прочего) смещение внутри файла каждой содержащейся в нем строки.

Например, вы можете выбрать самую простую структуру — список 32-битных целых чисел (по 4 байта каждое), каждое из которых представляет собой простое смещение от начала файла для строки, соответствующей одному и тому же числу, и иметь строки в файле завершаются NULL.

Например:

00000000: 0c000000 17000000 22000000 53747269  ........"...Stri
00000010: 6e67206f 6e650053 7472696e 67207477  ng one.String tw
00000020: 6f005374 72696e67 20746872 656500    o.String three.

Идея заключается в том, что вы можете найти в файле "String no * 4" и прочитать 4 байта как unsigned long (в порядке little endian, например использует Arduino), затем используйте это значение для повторного поиска. Отсюда вы можете читать байты, пока не нажмете \0, после чего вы поймете, что строка завершена.

В приведенном выше примере строка «String one» расположена в файле со смещением 12. Это 0x0C в шестнадцатеричном виде или 0x0c 0x00 0x00 0x00 в виде 32-битного целого числа с прямым порядком байтов. Это первые 4 байта файла. Итак, вы читаете их, интерпретируете как 32-битное целое число (12), а затем переходите к этому месту в файле, чтобы получить строку.

void readString(int num) {
    // Ищем запись индекса
    myFile.seek(num * 4);

    // Читаем запись индекса
    unsigned long offset = 0;
    myFile.read(&offset, 4);

    // Возможно, вы захотите добавить сюда проверку работоспособности

    // Ищем место, куда указывает индекс
    myFile.seek(offset);

    // Читаем каждый символ, пока не получим NULL.
    char c = myFile.read();
    while (c > 0) {
        Serial.write(c);
        c = myFile.read();
    }
    Serial.println();
}
,