stevemarple / IniFile

Arduino library to parse ini files.
GNU Lesser General Public License v2.1
87 stars 45 forks source link

update value #19

Closed erdirectoor closed 5 years ago

erdirectoor commented 5 years ago

Hi, i will like know if is possible update the value on file .ini

Thanks

tniercke commented 5 years ago

I would also like functions to update a value in the ini-file, such as setIniValue(...). Makes it in an ESP8266 with Webinterface much easier to save configs :-)

stevemarple commented 5 years ago

No, its not possible. I've updated README.md with information about this.

tfcroft4 commented 5 years ago

I have written an Insert value function for the ini library. I hope this helps Ted

I am using the Adafruit_SPIFlash library (v2.02) and running on a Sparkfun Red Turbo board which has SPI flash on board. The underlying file system is FatFS. You may need to edit for other file systems.

An extract from my test application:

/* three tests on the ini file
1   Replace value of existing key
2   Add a key and value to an existing section
3   Add a key and value to a new section
1 and 2 will write then rename a new file so is not fast
3 will just append to the existing file
uncomment each to test
*/
//Serial.println(" insertValue 'network', 'gateway', '192.168.1.10");
//ini.insertValue("network", "gateway","192.168.1.10",buffer, bufferLen);
Serial.println(" insertValue 'misc', 'gateway', '192.168.1.10");
ini.insertValue("misc", "gateway","192.168.1.10",buffer, bufferLen) ;
//Serial.println(" insertValue 'network3', 'gateway', '192.168.1.10");
//ini.insertValue("network3", "gateway","192.168.1.10",buffer, bufferLen) ;
ini.close();Serial.println();
bool IniFile::insertValue(const char* section, const char* key,const char* value,char* buffer, size_t len) 
{
  Adafruit_SPIFlash_FAT::File _filefrom;
  Adafruit_SPIFlash_FAT::File _fileto; //used when writing a copy of the file for update purpose
    char tofilename[INI_FILE_MAX_FILENAME_LEN];
    char c;
    uint8_t index =0;
    IniFileState state;
    int foundposition = 0, newpos = 0 , line=1;
     error_t errin , errout;
    // Call fatfs activate to make it the active chip that receives low level fatfs
    // Be sure to call activate before you call any fatfs functions yourself!
    fatfs.activate();
    while (!getValue(section, key, buffer, len, state)) { foundposition = state.readLinePosition;};
    #ifdef INIDEBUG
    Serial.print(section);Serial.print('\t');   Serial.print(key);Serial.print('\t');
    Serial.print(state.getValueState);Serial.print('\t');   Serial.print( foundposition );Serial.print('\t');
    Serial.print(state.readLinePosition);Serial.print('\t');    Serial.print(_error);Serial.print('\t');
    Serial.println(strlen(buffer));
    #endif
    // close ini file //
    _file.close();
    //open ini file and temp file
    //open from file read only
      _filefrom = fatfs.open(_filename, FILE_READ);
        if (!_filefrom) {
            Serial.println("Error, failed to open _file for reading!");
                _error = errorFileNotOpen;
                return false;
        }

  //open to file in write mode - create a temp file name that can be renamed on success
  do {
    tofilename[index]=_filename[index++];
    } while (_filename[index-1]!= '\0');
    tofilename[index-2] = '~';
#ifdef INIDEBUG //#endif
    Serial.print("From: ");Serial.println(_filename);
    Serial.print("  To: ");Serial.println(tofilename);
#endif
  if (fatfs.exists(tofilename)) fatfs.remove(tofilename);
  _fileto = fatfs.open(tofilename, FILE_WRITE); //Creates a new file to write;
  if (!_fileto) {
            Serial.println("Error, failed to open _fileto for writing!");
            _error = errorFileNotOpen;
            return false;
    }
    _filefrom.seek(0); //start at beginning
    _fileto.seek(0); //start at beginning
    switch ( _error) {
    case errorNoError:
    case errorKeyNotFound:
     {
    /* key found in section, copy to temp file from 0 upto found position,  insert new key value line, 
    if key exists then skip a line then copy to temp file from readline position to end of file */  
    //CopyPartFile(_filefrom, _fileto,0, previousposition);
    // move to our start point in from file
    _filefrom.seek(0);
    // test for reaching end point
#ifdef INIDEBUG //#endif    
    Serial.print(section);Serial.print('\t');   Serial.print(key);
    Serial.print("From ");Serial.print(0);Serial.print(" to "); Serial.println(foundposition);
    #endif
    while ((errin = readLine(_filefrom, buffer, len, newpos)) == errorNoError){
        uint8_t i = 0;
#ifdef INIDEBUG //#endif
        Serial.print(line++);Serial.print('\t');Serial.print(newpos);Serial.print('\t');Serial.print(foundposition);Serial.print('\t');
        Serial.println(buffer);     
#endif
        _fileto.println(buffer);

    if (newpos==foundposition) break;}

    if ( _error==errorNoError ) {
#ifdef INIDEBUG //#endif
    Serial.println(";Section and key were found, replaced key=value");
    _fileto.println(";Section and key were found, replaced key=value");
    line += 2;//inserted 2 lines
#endif
    readLine(_filefrom, buffer, len, newpos);//skip the old line with the value if errorNoError
    }
    else {
#ifdef INIDEBUG //#endif
Serial.println(";Section found but no key, new key=value");
_fileto.println(";Section found but no key, new key=value");
line += 2;//inserted 2 lines
#endif
}
    _fileto.print(key);_fileto.print(" = ");_fileto.print(value);_fileto.print('\n');//add new key=value to the temp file
#ifdef INIDEBUG //#endif
    Serial.print("Error is: ");Serial.println(_error);// 0 key found, 5 no section, 6 no key
    Serial.print("From ");Serial.print(newpos);Serial.print(" to "); Serial.println(_filefrom.fileSize());
#endif
        while ((errin = readLine(_filefrom, buffer, len, newpos)) == errorNoError){
            uint8_t i = 0;
#ifdef INIDEBUG //#endif
            Serial.print(line++);Serial.print('\t');Serial.print(newpos);Serial.print('\t');
            Serial.println(buffer);
#endif
            _fileto.println(buffer); //add line to temp file
        if (newpos==_filefrom.fileSize()) break;}   //end of input
    _fileto.println();
#ifdef INIDEBUG //#endif
    Serial.print("Case noError - Error is: ");Serial.println(_error);   
#endif
    _filefrom.close();_fileto.close();
    fatfs.remove(_filename); //fatfs function uses file path
    fatfs.rename(tofilename,_filename) ;

    break;
    }

    case errorSectionNotFound: {
    /*  if section NOT found, append new section to existing file needs to be writable  */
    _filefrom.close();
    _filefrom = fatfs.open(_filename, FILE_WRITE);
        Serial.print(section);Serial.println(" Not Found ");
            _filefrom.print('[');_filefrom.print(section);_filefrom.print(']');_filefrom.print('\n');           
            _filefrom.println(";A New Section.");
            _filefrom.print(key);_filefrom.print('=');_filefrom.print(value);_filefrom.print('\n');
    // close files //
    _filefrom.close();_fileto.close();
        break;
    }
    }

    _file = fatfs.open(_filename, FILE_READ); //re open inifile
    ;
    return _error == errorNoError;
}
tfcroft4 commented 5 years ago

For completeness this code will delete a key and a whole section if key is "". This has the same health warning. The function writes to a temporary file then renames it to the original.

bool IniFile::removeValue(const char* section, const char* key,char* buffer, size_t len) 
{
  Adafruit_SPIFlash_FAT::File _filefrom;
  Adafruit_SPIFlash_FAT::File _fileto; //used when writing a copy of the file for update purpose
    char tofilename[INI_FILE_MAX_FILENAME_LEN];
    char c;
    uint8_t index =0;
    IniFileState state;
    int previouspos,  foundposition = 0, newpos = 0 , line=1;
     error_t errin , errout;
     //if key is blank we will delete the section
     bool deletesection = (strlen(key)>0 ) ;
    // Call fatfs activate to make it the active chip that receives low level fatfs
    // Be sure to call activate before you call any fatfs functions yourself!
    fatfs.activate();
    while (!getValue(section, key, buffer, len, state)) {previouspos= foundposition ; foundposition = state.readLinePosition;};
    #ifdef INIDEBUG
    Serial.print(section);Serial.print('\t');   Serial.print(key);Serial.print('\t');
    Serial.print(state.getValueState);Serial.print('\t');   Serial.print( foundposition );Serial.print('\t');
    Serial.print(state.readLinePosition);Serial.print('\t');    Serial.print(_error);Serial.print('\t');
    Serial.println(strlen(buffer));
    #endif
    // close ini file //
    _file.close();
    //open ini file and temp file
    //open from file read only
      _filefrom = fatfs.open(_filename, FILE_READ);
        if (!_filefrom) {
            Serial.println("Error, failed to open _file for reading!");
                _error = errorFileNotOpen;
                return false;
        }

  //open to file in write mode - create a temp file name that can be renamed on success
  do {
    tofilename[index]=_filename[index++];
    } while (_filename[index-1]!= '\0');
    tofilename[index-2] = '~';
#ifdef INIDEBUG //#endif
    Serial.print("From: ");Serial.println(_filename);
    Serial.print("  To: ");Serial.println(tofilename);
#endif
  if (fatfs.exists(tofilename)) fatfs.remove(tofilename);
  _fileto = fatfs.open(tofilename, FILE_WRITE); //Creates a new file to write;
  if (!_fileto) {
            Serial.println("Error, failed to open _fileto for writing!");
            _error = errorFileNotOpen;
            return false;
    }
    _filefrom.seek(0); //start at beginning
    _fileto.seek(0); //start at beginning
    switch ( _error) {
    case errorNoError:
    case errorKeyNotFound:
     {
    /* key found in section, copy to temp file from 0 upto found position,  insert new key value line, 
    if key exists then skip a line then copy to temp file from readline position to end of file */  
    //CopyPartFile(_filefrom, _fileto,0, previousposition);
    // move to our start point in from file
    _filefrom.seek(0);
    // test for reaching end point
#ifdef INIDEBUG //#endif    
    Serial.print(section);Serial.print('\t');   Serial.print(key);
    Serial.print("From ");Serial.print(0);Serial.print(" to "); Serial.println(foundposition);
    #endif
    while ((errin = readLine(_filefrom, buffer, len, newpos)) == errorNoError){
        uint8_t i = 0;
#ifdef INIDEBUG //#endif
        Serial.print(line++);Serial.print('\t');
        Serial.print(newpos);Serial.print('\t');
        Serial.print(foundposition);Serial.print('\t');
        Serial.println(buffer);     
#endif

        _fileto.println(buffer);

    if (newpos==foundposition) break;}

    if ( _error==errorNoError ) { //found the key
#ifdef INIDEBUG //#endif
    Serial.println(";Section and key were found, remove key");
    _fileto.println(";Section and key were found, remove key");
    //line += 2;//inserted 2 lines
#endif
    readLine(_filefrom, buffer, len, newpos);//skip the old line with the value if errorNoError
    }
    else {
#ifdef INIDEBUG //#endif
Serial.println(";Section found but not blank key");
Serial.print(foundposition);Serial.print('\t');
Serial.print(_filefrom.position());Serial.print('\t');
Serial.println(_fileto.position());
_fileto.println(";Section found but not blank key");
// where did this key start foundposition and where is next key
//truncate file ? //backup write position
// rewind seek to foundposition then find the next '['
//reset _fileto and copy up to foundposition
_fileto.seek(previouspos);
 _filefrom.readStringUntil('[');
//continue reading  writing lines from here
newpos = _filefrom.position()-1;
Serial.print(foundposition);Serial.print('\t');
Serial.print(_filefrom.position());Serial.print('\t');
Serial.println(_fileto.position());
//line += 2;//inserted 2 lines
#endif
}
    //_fileto.print(key);_fileto.print(" = ");_fileto.print(value);_fileto.print('\n');//don't write the key
#ifdef INIDEBUG //#endif
    Serial.print("Error is: ");Serial.println(_error);// 0 key found, 5 no section, 6 no key
    Serial.print("From ");Serial.print(newpos);Serial.print(" to "); Serial.println(_filefrom.fileSize());
#endif
        while ((errin = readLine(_filefrom, buffer, len, newpos)) == errorNoError){
            uint8_t i = 0;
#ifdef INIDEBUG //#endif
            Serial.print(line++);Serial.print('\t');Serial.print(newpos);Serial.print('\t');
            Serial.println(buffer);
#endif
            _fileto.println(buffer); //add line to temp file
        if (newpos==_filefrom.fileSize()) break;}   //end of input
    _fileto.println();
#ifdef INIDEBUG //#endif
    Serial.print("Case noError - Error is: ");Serial.println(_error);   
#endif
    _filefrom.close();_fileto.close();
    fatfs.remove(_filename); //fatfs function uses file path
    fatfs.rename(tofilename,_filename) ;

    break;
    }

    case errorSectionNotFound: {
    /*  if section NOT found do nothing*/
    _filefrom.close();
    _filefrom = fatfs.open(_filename, FILE_WRITE);
        Serial.print(section);Serial.println(" Not Found ");
    // close files //
    _filefrom.close();_fileto.close();
        break;
    }
    }

    _file = fatfs.open(_filename, FILE_READ); //re open inifile
    ;
    return _error == errorNoError;
}