【发布时间】:2018-05-11 10:38:56
【问题描述】:
我有一个从 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 的最大因素,但这似乎每次调用此函数时都需要运行。有没有一个优雅的解决方案让我眼前一亮?
【问题讨论】:
-
uint8_t buffer[w];-- 这不是有效的 C++。 C++ 中的数组的大小由常量表达式表示,而不是运行时变量或运行时计算表达式。如果您想要 C++ 中的标准动态数组声明,请使用std::vector<uint8_t> buffer;。 -
Paul,这方面的代码工作得很好。也许这与处于 arduino 环境中有关。我真的不知道,因为 arduino 是我唯一的 C++ 经验。
-
@PaulMcKenzie OP 不能使用
vector,它是 arduino。 Arduino不支持很多STL(因为不支持动态分配)。在 OP 的情况下,VLA 是一个正确的解决方案。 -
available()告诉您可以阅读多少,因此使用它来跟踪缓冲区的哪些部分是有效的。我认为File.read()会返回实际读取的字节数,但文档似乎没有区分单字节调用和填充缓冲区的调用。 -
@RetiredNinja 我只花了 25 分钟梳理了一遍,事实上,它确实返回了读取的字节数 - 请参阅我的答案。文档是错误的,很可能(根据为 Arduino 打开的票证)稍后添加了缓冲版本的读取,但没有人注意正确更新文档 - 新功能只是添加到描述中。我没有留下深刻的印象:D
标签: c++ arduino arduino-esp8266