Редактирование определенной позиции в файле, хранящемся на SD-карте
Я пытаюсь сохранить некоторые переменные в текстовом файле, который сохраняется на SD-карте, используя SD-библиотеку. Каждый раз, когда моя программа запускается, она загружает значения этих переменных из файла. Через несколько минут моя программа попытается изменить значение некоторых переменных (не всех).
Это то, что я сделал бы в программе на языке Си. Я бы нашел позицию (используя position()), в которой присутствуют редактируемые значения, а затем, используя функцию seek(), я бы записал в заданной позиции, перезаписав таким образом файл.
Каждая переменная хранится в отдельной строке. Но по какой-то причине программа записывает только в конец файла, даже если я переместил указатель на файл в другое место. Как я могу выполнить вышеуказанную задачу?
Простой пример кода выглядит следующим образом:
#include <SD.h> //Загрузить библиотеку SD
int chipSelect = 53;
File file;
void setup() {
// поместите сюда свой установочный код, чтобы запустить его один раз:
Serial.begin(9600);
pinMode(chipSelect, OUTPUT); // pin выбора микросхемы должен быть установлен в режим ВЫВОДА
Serial.print("Welcome!");
Serial.println();
bool initialization_state = SD.begin(chipSelect);
delay(400); // SD-карте требуется некоторое время для инициализации
if (!initialization_state) { // Инициализировать SD-карту
Serial.println("Could not initialize SD card."); // если возвращаемое значение равно false, что-то пошло не так
} else { // если возвращаемое значение равно true
Serial.println("SD card initialized");
}
SD.remove("misc.txt");
file = SD.open("misc.txt",FILE_WRITE);
file.print("Once you know the central idea and a rough plan for your paragraphs, you need to arrange them in a certain manner to get your story across.");
file.println();
file.print("Following are some possible ways of organizing your paragraphs.");
file.println();
file.print("Narration: Tell a story. Go chronologically, from start to finish. Description: Provide specific details about what something looks, smells, tastes, sounds, or feels like.");
file.println();
file.print("Organize spatially, in order of appearance, or by topic. Process: Explain how something works, step by step. Perhaps follow a sequence—first, second, third.");
file.close();
read_file();
Serial.print("Read?");
Serial.println();
update_file();
read_file();
}
void loop() {
// поместите сюда свой основной код для повторного запуска:
}
void read_file() {
Serial.println("--- Reading file ---");
file = SD.open("misc.txt", FILE_READ);
char character;
while( (character = file.read()) != -1) {
Serial.print(character);
}
Serial.println();
file.close();
}
void update_file() {
file = SD.open("misc.txt", FILE_READ);
char character;
while( (character = file.read()) != '\n') {}
byte pos = file.position();
file.close();
file = SD.open("misc.txt", FILE_WRITE);
file.seek(pos);
file.print(" Love, love, love.");
file.close();
}
В этой программе я пытаюсь перезаписать вторую строку. Цикл while прерывается при первом символе новой строки. Я сохраняю местоположение первого символа во второй строке в переменной pos. Затем я открываю объект file для записи, ищу позицию, в которой я хочу записать (используя file.seek(pos)), а затем печатаю в файл. Но когда я читаю файл, в конце написан текст "Люблю, люблю, люблю".
Я использую linux Arduino IDE 1.8.9.
1 ответ
Лучший ответ:
Проблема в том, что вы открываете файл с помощью FILE_WRITE
. Это комбинированный макрос, который состоит из:
#define FILE_WRITE (O_READ | O_WRITE | O_CREAT | O_APPEND)
Ключевым из них является O_APPEND
. В исходном коде (SdFile.cpp) т говорит:
O_APPEND - Если задано, смещение файла должно быть установлено в конец файла перед каждой записью.
Таким образом, поиск ничего не делает, если установлен параметр O_APPEND, поскольку он переопределяется.
Поэтому вместо этого вам нужно открыть файл без O_APPEND
. На самом деле вам вообще не нужно закрывать и открывать файл, так как при правильном открытии вы можете перемещаться по желанию, читая и записывая. Флаг O_RDWR
представляет собой комбинацию O_READ
и O_WRITE
.
Например:
void update_file() {
file = SD.open("misc.txt", O_RDWR);
char character;
while( (character = file.read()) != '\n') {}
file.print(" Love, love, love.");
file.close();
}
Флаг O_CREAT
, который является частью FILE_WRITE
, создаст новый файл, если вы попытаетесь открыть тот, который не существует. Если опустить это, SD.open
завершится неудачей, если файл, который вы пытаетесь изменить, не существует.
Разве file.seek(file.position());
не является ошибкой?, @Edgar Bonet
@EdgarBonet Наверное, да., @Majenko
- NodeMCU V3 + SD-карта с Arduino IDE Не работает
- Как получить свободное/использованное место на SD-карте и передать его
- Arduino SD подсчитывает файлы и открывает их последним, как это сделать?
- Есть ли способ снять ограничение имени файла 8.3 в библиотеке SD.h?
- Ошибка чтения/записи SD-карты Arduino Mega
- Как **получить** атрибуты для файлов SD?
- Чтение изображений bmp с SD-карты, преобразование их и отображение на последовательном мониторе в Arduino
- Преобразовать байтовый текстовый файл в массив
Лично я бы прочитал файл построчно, записывая каждую строку во временный файл. Затем вы меняете строки, которые нужно менять на лету. После этого вы удаляете старый файл и переименовываете временный файл на старое имя. Таким образом, вы сможете легче обрабатывать изменения в объеме данных., @Majenko
@Majenko Хорошо. Но мне было интересно, может ли мой подход быть выполнен на arduino? Разве библиотека SD не поддерживает его?, @Mohammed Arshaan
Нет причин, почему бы и нет. Однако: откуда вы знаете, что вы не ищете до конца файла?, @Majenko
Потому что когда-то я нашел и сохранил pos. Я закрыл файловый объект. Затем открыл другой файловый объект в FILE_READ, использовал file.seek (pos), чтобы перейти к местоположению, и распечатал оставшийся файл на последовательном мониторе. Это сработало., @Mohammed Arshaan