文件大小和缓冲区过冲

file size and buffer overshoot

我有一个函数可以从 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()) 的最后一个循环,在那里它们读取文件的末尾,但随后继续读取缓冲区,缓冲区的尾端填充了上一个循环的数据,那不是' t 被最新的 f.read() 覆盖。如何确保 while(f.available()) 函数的最后一个循环仅使用当前循环期间写入缓冲区的信息?我现在唯一的想法是解决文件大小的因素,将缓冲区大小设置为小于3072的最大因素,但这似乎每次调用该函数时都运行。有什么优雅的解决方案吗?

您的程序运行不正确,因为 f.read() 不能保证读取整个缓冲区。此外,当您读取文件的最后一块时,它一定会发生,除非文件大小是缓冲区大小的一个因素(在您的情况下为 3072)。

虽然 Arduino 规范(https://www.arduino.cc/en/Reference/FileRead) doesn't say so, SD.read function returns the number of bytes read. See code of the library here: https://github.com/arduino-libraries/SD/blob/master/src/utility/SdFile.cppint16_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];