размер файла и превышение буфера - PullRequest
0 голосов
/ 11 мая 2018

У меня есть функция, которая открывает файл с SD-карты, использует размер файла для установки размера буфера, записывает блок информации в этот буфер, а затем что-то делает с этой информацией, как показано в этом коде:

char filename = "filename.txt";
uint16_t duration;
uint16_t pixel;
int q = 0;
int w = 0;
bool largefile;
File f;
int readuntil;
long large_buffer;

f = SD.open(filename);

if(f.size() > 3072) {
    w = 3072;
} else {
    w = f.size();
}
uint8_t buffer[w];

while(f.available()) {
    f.read(buffer, sizeof(buffer));

    while(q < sizeof(buffer)) {
        doStuffWithInformation(buffer[q++]);
    }
    q=0;
}
f.close;

Это прекрасно работает с файлами меньшего размера, но с объемом жесткого буфера, превышающим 3072 (к которому я пришел опытным путем, это просто объем памяти, который можно безопасно выделить для этой функции),сталкивается с проблемой.Большие файлы читаются нормально до тех пор, пока они не достигнут последнего цикла while(f.available()), где они читают конец файла, но затем продолжают чтение буфера, конец которого заполняется данными из последнего цикла, которые не были перезаписаныпо последним f.read().Как я могу убедиться, что последний цикл функции while(f.available()) работает только с информацией, записанной в буфер во время текущего цикла?Моя единственная идея сейчас состоит в том, чтобы определить факторы размера файла и установить размер буфера как самый большой фактор меньше 3072, но это кажется интенсивным, чтобы запускаться каждый раз, когда вызывается эта функция.Есть ли элегантное решение, которое смотрит мне в лицо?

1 Ответ

0 голосов
/ 11 мая 2018

Ваша программа работает неправильно, потому что f.read() не гарантирует чтение всего буфера.Более того, это обязательно произойдет, когда вы прочитаете последний фрагмент файла, если только размер файла не является фактором размера буфера (3072 в вашем случае).

Хотя спецификация Arduino (https://www.arduino.cc/en/Reference/FileRead))не говорит об этом, функция SD.read возвращает количество прочитанных байтов. См. код библиотеки здесь: https://github.com/arduino-libraries/SD/blob/master/src/utility/SdFile.cpp, int16_t SdFile::read(void* buf, uint16_t nbyte)

Зная это, вы должны изменить свой цикл следующим образом (в то же время переписывая его как цикл for для лучшей читаемости и удаляя приведенное выше определение q:

while(f.available()) {
    uint16_t sz = f.read(buffer, sizeof(buffer));

    for (uint16_t q = 0; q < sz; ++q) {
        doStuffWithInformation(buffer[q]);
    }
}

Кстати, теперь, когда у вас есть эта логика, это будет иметь смыслчтобы вы покончили с массивом переменной длины и использовали фиксированный буфер размером 512 - стандартный размер сектора на SD-карте. Скорее всего, он даст такую ​​же производительность в отношении чтения и немного лучшую производительность в отношении sizeof, которая становится постоянной времени компиляции, а не вычислением времени выполнения. Это также упрощает вашу программу. Это делает для следующего кода:

f = SD.open(filename);
...
uint8_t buffer[512];
...