Hi everyone,
is there any way for quick writing/reading objects to/from txt file or I should just write the text manualy with LittleFS and read then parse everything to recreate objects?
looking for the most efficient way
thank you!
Hi everyone,
is there any way for quick writing/reading objects to/from txt file or I should just write the text manualy with LittleFS and read then parse everything to recreate objects?
looking for the most efficient way
thank you!
chris700:
looking for the most efficient way
Then don't use a text file. Write / read them in binary.
I guess by “efficient” you also mean without writing a lot of code.
I’d probably define a struct to represent the data members of my object and use a union to treat that struct as a byte array, then stream the bytes to a file. This is restricted to simple data types.
Otherwise google for “serialize c++ object to file” or similar.
6v6gt:
I’d probably define a struct to represent the data members of my object and use a union to treat that struct as a byte array, then stream the bytes to a file.
No need for such gyrations. You can get a byte pointer that points to the start of the object with:
uint8_t *objectPointer = (uint8_t *)&myObject;
And, this will give you the number of bytes:
const size_t numBytes = sizeof(myClass);
You can stream the bytes from there.
But, this will only do a byte-for-byte, shallow copy. It will fail if the object contains pointers, references or other objects that contain pointers or references. It will also fail to stream the value of any static data members.
So, OP will have to provide more details about the problem that actually needs to be solved.
thanks to both of you for your suggestions, i will search for serialize c++ object to file but i dont understand gfvalvo "Write / read them in binary." .
what do you mean by that?
thank you
Edit:
I understand you mean binary file.
How would I remove an entry from txt/binary file? Locating the line and then removing this line? And by removing means "rewrite" the whole file without this line..too much work isnt it?
Would it be better to just have different text/binary file for every object of a class(and different folder for every class) or that would mean too much space in the system?
chris700:
but i dont understand gfvalvo "[/color]Write / read them in binary." .
what do you mean by that?
thank you
The title of your thread is "Best way of writing/reading classes-objects to/from txt file". A "text file" contains ASCII characters. That implies that you want to convert all of the object's data members to human-readable ASCII and store them in a file.
But, since you also requested the "most efficient way", I suggested storing the data members in their native binary format. IMO, that's more "efficient", at least in terms of file size, execution speed, and coding effort.
So, it seems that you have conflicting requirements. Hence my question: What problem are your trying to solve?
chris700:
. . .
Would it be better to just have different text/binary file for every object of a class(and different folder for every class) or that would mean too much space in the system?
Give an example of what you are doing.
Maybe the data structures can be redesigned so these are easier to dump out to a file or file(s).
Will be running a software on ESP32 module which will get inputs(configuration) from internet and/or serial.
Current data will be objects on RAM.
When a value of an object is changed either serially or from the internet, my code will detect the change and load the change to the object(s).
By putting everything on a txt file (either ascii or binary as you suggested) is like a "database". However it requires much more code i guess to locate a line and edit it because editing it means probably "rewrite" the whole file and it will take resources and time.
I was thinking to have for every object(instance) /name_of_class1/filename_the_id_of_instance.txt so when a change is made only this file will be "rewrited" which doesnt take a lot of resources and its quicker that locating lines etc.just delete and write this file with the "up to date" data (either from online or from serial).
makes sense?
Please provide the declaration of said class.
BTW, a .txt file can't be "either ascii or binary". A .txt file is by definition ASCII. A binary file is binary.
If it is just configuration information, you probably don't want multiple instances of it. This is, for example, what I use for a ESP8266 clock. It is stored in (emulated) EEPROM and read during setup(). If something changes, or at the initial configuration, it is written back to EEPROM at the time it changes.
struct config_t {
char eepromLayourVersion[5]; // magic string
char clockName[12];
bool noWlan ;
char ssid[32];
char psk[64];
char timeServer[64];
uint16_t syncInterval;
char tzName[12];
byte custTzStdWeek;
byte custTzStdDow;
byte custTzStdMonth;
byte custTzStdHour ;
int16_t custTzStdOffset ;
byte custTzDstWeek ;
byte custTzDstDow ;
byte custTzDstMonth ;
byte custTzDstHour ;
int16_t custTzDstOffset ;
// byte clockNetMode ; // 0= "Standalone", 1="WLAN-Config-with-NTP", 2="WLAN-Config-without-NTP"
byte dacInputLevel ; // 0 .. 255
byte playTime ; // seconds.
bool scrollDisplay ;
} ;
6v6gt:
If it is just configuration information, you probably don't want multiple instances of it. This is, for example, what I use for a ESP8266 clock. It is stored in (emulated) EEPROM and read during setup(). If something changes, or at the initial configuration, it is written back to EEPROM at the time it changes.struct config_t {
char eepromLayourVersion[5]; // magic string
char clockName[12];
bool noWlan ;
char ssid[32];
char psk[64];
char timeServer[64];
uint16_t syncInterval;
char tzName[12];
byte custTzStdWeek;
byte custTzStdDow;
byte custTzStdMonth;
byte custTzStdHour ;
int16_t custTzStdOffset ;
byte custTzDstWeek ;
byte custTzDstDow ;
byte custTzDstMonth ;
byte custTzDstHour ;
int16_t custTzDstOffset ;
// byte clockNetMode ; // 0= "Standalone", 1="WLAN-Config-with-NTP", 2="WLAN-Config-without-NTP"
byte dacInputLevel ; // 0 .. 255
byte playTime ; // seconds.
bool scrollDisplay ;
} ;
sorry i need instances, since the configuration refers to the configuration of the object. sorry language barrier.
do you think different file would be the best option? or too much space
I can't visualise what you are doing, but the file system is certainly an option, especially if the number of "objects" is not fixed and/or their size varies. If you are getting the data in a serial form and storing it in a serial form (somehow), it may, however, be that an object oriented model is not appropriate for this task.
One more try:
gfvalvo:
Please provide the declaration of said class.
gfvalvo:
One more try:
class MyClass{
private:
String cryptoid;
String dname;
byte enabled;
byte type;
public:
MyClass(String cryptoid,String dname, byte enabled, byte type){
this->cryptoid=cryptoid;
this->dname=dname;
this->enabled=enabled;
this->type=type;
String get_cryptoid(){
return cryptoid;
}
String get_dname(){
return dname;
}
...
...
Myclass mc1("xxxx","yyyy",0,0);
Also how can i make something like a loop that creates objects and put it on an array(or List like in c#)?
I tried:
for(int i = 0; i <= 50; i++){
Myclass mc[i]("xxxx","yyyy",0,0);
}
but doesnt work..
That fact that your class contains members that are instances of the String class will complicate your life. That class uses pointers and dynamic allocation. Thus, as I mentioned in Reply #3, a simple, shallow byte for byte serialization will not be possible.
By the way, since you're concerned with efficiency, the passing of String parameters in and out of the class's methods is quite inefficient. Every function call and return is making copies of the String objects on the stack and dynamic allocation of the character arrays themselves. It's not as much of a problem on your ESP as say an Uno. But, it sure is a lot of memory thrashing. You should consider passing references. Or, better yet, dump the String class and work directly with character arrays.
chris700:
Also how can i make something like a loop that creates objects and put it on an array(or List like in c#)?
Something like this:
myClass *mc[50];
void setup() {
for (uint8_t i=0;i<50;i++) {
mc[i] = new myClass("xxxx");
}
.
.
}
The data type String is not simple and is not very amenable to serialization because it has a variable length. Are cryptoid and dname variable length or is there always a (reasonable) maximum length which cannot be exceeded ?
Edit
Post crossed with @gfvalvo
6v6gt:
The data type String is not simple and is not very amenable to serialization because it has a variable length. Are cryptoid and dname variable length or is there always a (reasonable) maximum length which cannot be exceeded ?Edit
Post crossed with @gfvalvo
cryptoid can be fixed, dname depends on the user but yea will have a limit of like 20 characters
gfvalvo:
That fact that your class contains members that are instances of the String class will complicate your life. That class uses pointers and dynamic allocation. Thus, as I mentioned in Reply #3, a simple, shallow byte for byte serialization will not be possible.By the way, since you're concerned with efficiency, the passing of String parameters in and out of the class's methods is quite inefficient. Every function call and return is making copies of the String objects on the stack and dynamic allocation of the character arrays themselves. It's not as much of a problem on your ESP as say an Uno. But, it sure is a lot of memory thrashing. You should consider passing references. Or, better yet, dump the String class and work directly with character arrays.
Something like this:myClass *mc[50];
void setup() {
for (uint8_t i=0;i<50;i++) {
mc[i] = new myClass("xxxx");
}
.
.
}
Would it work without *? Can you please explain to me why use pointer? thank you in advance
chris700:
Would it work without *?
No
Can you please explain to me why use pointer?
Because the 'new' operator returns a pointer to the dynamically created object. 'new' is the C++ analog of malloc() from the good-old C language. malloc() also returns a pointer.
gfvalvo:
NoBecause the 'new' operator returns a pointer to the dynamically created object. 'new' is the C++ equivalent of malloc() in good old C language. malloc() also returns a pointer.
I have been programming for few years in vb.net and generally .net framework.i was always avoiding using * coz i dont really understand it. ill try find some youtube videos to understand it thanks ill test your code tonight