SdFat. Удаление строки из txt. Вставить текст в середину или начало

Muramur2000
Offline
Зарегистрирован: 11.11.2020

Всем привет!. Заранее  предупреждаю: я малость тупой.

Есть у меня Sd карта на 8гб FAT32, и ардуино Due. Использую библиотеку SDFat. Задача следующая:

   есть файл, с настройками например, типа:

name = Илья
IDcart = 2268284959
password = 7524
dostup_mode = 0

lv0_coutn = 5
lv0_chance = 50

Парсинг проблем не вызывает. Но мне хочется еще и менять настройки. Например password задать 12345678. write и print затирают старые символы, а мне нужно удалить все между '=' и '\n'. Я не нашёл метода, что бы делал это(Вообще я не нашёл описания методов для SDfat, только для SD. Буду рад если кто-нибудь поделется ссылочкой, если такая имеется), поэтому приступил к написанию своих функций. С вставкой я справился хоть и не оптимально. Приходится пробегать по всему файлу по байту. Если файл маленький, то не критично, но а вдруг нет? А как удалять вообще не представляю. Вот что я имею. Тесты провожу на файле с :

Hello, world!!! Test file.

На выходе:

String123456789, world!!! Test file.  le.  

Код:

#include "SdFat.h"

SdFat SD;
const int chipSelect = 4;
// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(chipSelect, DEDICATED_SPI, SD_SCK_MHZ(16))
#else  // HAS_SDIO_CLASS
#define SD_CONFIG SdSpiConfig(chipSelect, SHARED_SPI, SD_SCK_MHZ(16))
#endif  // HAS_SDIO_CLASS
void insert(File &file, char * str, unsigned long poz){
  unsigned long len = strlen(str), siz=file.size();
  char c; 
  file.seek(siz);
  for (unsigned long i = 0; i=poz and i!= 0xFFFFFFFF ); i--){
    file.seek(i);
    c = file.peek();
    Serial.println(c);
    file.seek(i+len);
    file.write(c);
    }
  file.seek(poz);
  file.write(str, len);
  }

void insert(File &file, String &str, unsigned long poz){
  unsigned long len = str.length(), siz=file.size();
  char c; 
  file.seek(siz);
  for (unsigned long i = 0; i=poz and i!= 0xFFFFFFFF ); i--){
    file.seek(i);
    c = file.peek();
    file.seek(i+len);
    file.write(c);
    }
  file.seek(poz);
  file.write(str.c_str(), len);
  }

void removetxt(File &file, unsigned long pos, unsigned long count){
  unsigned long siz=file.size();
  char c; 
  for (unsigned long i = pos+count; i < siz; i++) {
     file.seek(i);
     c = file.peek();
     file.seek(i-count);
     file.write(c);
    }
  //как удалить count последних символов из файла???
  }
  
void setup() {
  Serial.begin(9600);
  while ( !SD.begin( SD_CONFIG )) {
    Serial.println("initialization failed!");
    delay(1000);
  }
  Serial.println("initialization OK!");

  File myFile = SD.open("tasks/test1.txt", FILE_WRITE);

  if (myFile) {
    unsigned long s = myFile.size();
    unsigned long p = myFile.position();
    Serial.println(s);
    Serial.println(p);
    insert(myFile, "123456789", 0); // Вставим в начало
    String my_s = "String";
    insert(myFile, my_s, 0); // Вставим в начало
    removetxt(myFile, 15, 5); // удаляем слово Hello
    
   
    myFile.close();
  } else  Serial.println("open failed!");

}

void loop() {}
rkit
Онлайн
Зарегистрирован: 23.11.2016

Пишешь новый файл с нуля, переименуешь его на место старого.

Muramur2000
Offline
Зарегистрирован: 11.11.2020

rkit пишет:

Пишешь новый файл с нуля, переименуешь его на место старого.

А можно с примерчиком? 

rkit
Онлайн
Зарегистрирован: 23.11.2016

Ок. Побежал покупать оборудование, собирать, писать и отлаживать тебе примерчик. Жди.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Muramur2000 пишет:

А можно с примерчиком? 

А можно 800р?

Muramur2000
Offline
Зарегистрирован: 11.11.2020

Я просто не представляю как создать пустой файл, заполнить его и лишь потом его сохранить с нужным именем. Я могу сохранить новый файл, например test2.txt. Сделать там всё что нужно. Сохранить. Удалить  исходник. Скопировать с нужным именем и удалить test2.txt. Ну как то... Кажется вы не это имели в виду. И если подгружать весь файл в оперативку, а он скажем 1000 строк, хватит ли оперативки? 

Muramur2000
Offline
Зарегистрирован: 11.11.2020

Короче меня интересует лишь как создать файл не повредив исходник и только в конце их пересохранить. 

Bruzzer
Offline
Зарегистрирован: 17.03.2020

Приведенный вами пример с ошибками и не компилируется.

SuperXL
Offline
Зарегистрирован: 30.12.2011

Muramur2000 пишет:

Короче меня интересует лишь как создать файл не повредив исходник и только в конце их пересохранить. 

Если не хотите создавать второй файл в памяти чтоб его сохранить, а затем удалить исходник и переименовать вновь созданный файл, попробуйте другой алгоритм.

Т.к. у Вас файл настроек имеет статичный характер "параметр" = "значение" значит нужна самописная функция, которая способна сформировать такую строку целиком и записать ее в файл.

Вы используете String, поэтому пример будет содержать этот класс. 

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

далее открываем файл настроек (имя файла настроек), открываем временный файл, проверяем открылись ли, если нет кричим в терминал ошибку - где затык, вываливаемся из функции с возвратом false. Если все хорошо, в цикле пока есть что читать начинаем читать построчно файл настроек, парсим каждую строку на предмет наличия параметра, если параметр найден, заменяем прочитанную строку новой с новым параметром, и записываем ее во временный файл, если строка с параметром не найдена, то оставляем прочитанную строку без изменений и пуляем ее во временный файл. Всё, все строки закончились, закрываем оба файла. Проверяем был ли найден параметр, если нет, то вываливаемся с ошибкой. Если был найден, пытаемся удалить уже старый файл настроек, если все хорошо, пытаемся переименовать временный файл в файл с именем "имя файла настроек" если все хорошо, то выходим из функции с возвратом true. Как-то так...

Внимание!!!, нижеприведенный пример НЕ проверялся на корректность, правильность, грамотность, оптимальность, а был написан на скорую руку, на коленке быдлокодом. Скорее всего в примере есть ошибки, прошу Вас проверить работоспособность, т.к. на данный момент нет карточки и железа под рукой.

Пример: 

bool update_settings(String settings_file_name, String argument, String value){

  bool ret = false;

  File settingFile = SD.open(settings_file_name, FILE_READ);
  if (!settingFile){
    Serial.println("Error: settings file not found, or card error !");
    return false;
  }
  
  File tmpFile = SD.open("/tmp_settings.txt", FILE_WRITE);
  if (!tmpFile){
    Serial.println("Error: can't create tmp_settings.txt. Write protect?, No free space ?");
    return false;  
  }

  while(settingFile.available()){
    String tmp_str = settingFile.readString();
    if (tmp_str.indexOf(argument) > -1) {
      ret = true;
      tmp_str = argument + " = " + value;
      Serial.println("OK, argument found.");
    }
    tmpFile.println(tmp_str);
  }
  
  settingFile.close();
  tmpFile.close();
  
  if (!ret) {
    Serial.println("Error: argument not found. !");
    SD.remove("/tmp_settings.txt");
    return false;
  }
  if (!SD.remove(settings_file_name)) {
    Serial.println("Error with remove old settings file ! Write protect ?");
    return false;
  }

  if (!SD.rename("/tmp_settings.txt", settings_file_name)){
    Serial.println("Error with rename tmp settings file ! Write protect ?");
    return false;
  }
  rerurn true;
}
b707
Offline
Зарегистрирован: 26.05.2017

Данный пример предполагает, что строчки " параметр = значение" расположены строго на отдельных строчках, а если это не так - будет тыква

SuperXL
Offline
Зарегистрирован: 30.12.2011

само собой будет тыква ))) я просто ориентировался на файл настроек автора темы. 

rkit
Онлайн
Зарегистрирован: 23.11.2016

По секрету скажу, что в реальной задаче настройки уже загружены в память.

b707
Offline
Зарегистрирован: 26.05.2017

Ну я других ошибок не искал... Сижу в магазине жену жду, она пошла что-то мерять, это надолго:)