Удалить строки в SPIFFS (ESP8266 / Arduino)

Я пытаюсь создать функцию, которая удалит строку из текстового файла, хранящегося в SPIFFS, на ESP8266. Я попытался использовать метод перезаписи пространства, найденный здесь https://forum.arduino.cc/index.php?topic=344736.msg2380000#msg2380000, но я просто получаю строку пробелов.

Насколько я понимаю, он должен работать, как показано ниже, где - представляет собой заменяемые пробелы. В рассматриваемом файле есть только \n в конце строки.

Before
======
This is a line of text\n
This is another line of text\n
And here is another
Replace line 2 with spaces
==========================
This is a line of text\n
----------------------------\n
And here is another
Desired result
==============
This is a line of text\n
And here is another

На самом деле я получаю следующее.

Actual result
=============
This is a line of text\n
                            \n
And here is another

Размер файла также остается прежним.

Вот функция deleteLine, которую я использую.

bool deleteLine (char* path, uint32_t lineNum) {
  if (!SPIFFS.begin()) {
    Serial.println("SPIFFS failed!");
    SPIFFS.end();
    return false;
  }
  File file = SPIFFS.open(path, "r+");
  if (!file) {
    Serial.println("File open failed!");
    file.close();
    SPIFFS.end();
    return false;
  }
  uint32_t size = file.size();
  file.seek(0);
  uint32_t currentLine = 0;
  bool lineFound = false;

  for (uint32_t i = 0; i < size; ++i) {
    if (currentLine == lineNum) {
      lineFound = true;
      for (uint32_t j = i; j < size; ++j) {
        uint32_t currentLocation = j;
        char currentChar = (char)file.read();
        if (currentChar != '\n') {
          file.seek(j);
          file.write(' ');
        } else {
          break;
        }
      }
      break;
    }
    char currentChar = (char)file.read();
    if (currentChar == '\n') {
      ++currentLine;
    }
  }
  file.close();
  SPIFFS.end();
  if (lineFound) {
    return true;
  } else {
    return false;
  }
}

Я что-то здесь делаю глупо?

Я знаю, что я могу создать новый файл, скопировать исходный файл, пропустив строку, однако я работаю с 2x файлами размером около 1 МБ каждый, и мне потребуется дополнительное свободное пространство 1 МБ для временного файла, что не идеально .

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


person Pinja    schedule 18.12.2019    source источник
comment
Я не думаю, что есть решение. Даже если вы хотите отредактировать файл, вам нужно удалить старый и записать новый, если они имеют другой размер. Если вы можете разделить свой большой файл на небольшие файлы размером всего 16 КБ, вы можете загрузить весь файл в ОЗУ в виде строки и сохранить ее снова после удаления всех строк.   -  person Adriano    schedule 18.12.2019
comment
единственный способ удалить часть в середине файла - это прочитать файл и записать новое содержимое в новый файл. затем удалите старый файл и переименуйте новый файл. это относится и к большинству компьютерных файловых систем.   -  person Juraj    schedule 18.12.2019


Ответы (1)


Что вы хотите сделать, так это напрямую записать на низком уровне в файловую систему, что делается по предоставленной ссылке (так, на микроконтроллерах с HW / SW с открытым исходным кодом у вас есть больше возможностей, чем просто чтение и запись файлов, как на ПК на базе ПК). ОПЕРАЦИОННЫЕ СИСТЕМЫ).

  for(uint8_t i=0;i<32;i++) ch[i]=' '; 

попробуйте заменить на

 for(uint8_t i=0;i<32;i++) ch[i]='X';

и вы увидите, что это работает (по крайней мере, для меня). Я работаю с динамической длиной строки = количество символов от предыдущего \ n до \ n строки, которую нужно перезаписать. На всякий случай проверяю размер файла. И время от времени я сжимаю файл, переименовывая старый файл в bak, удаляя все «пустые» строки, игнорируя их при записи в новый файл в SPIFFS. Работает безупречно для большого файла конфигурации 64kb max.

person Codebreaker007    schedule 22.03.2020