user48730: I'm trying to store (read&write( a struct using LittleFS on ESP8266.
Appreciate assistance
struct oper_string
{
  bool state;     /* On or Off */
  uint8_t step;   /* Step, in case of PWM */
  uint8_t reason; /* What triggered the button */
  time_t ontime;  /* Start Clk */
  time_t offtime; /* Off Clk */
};


user7508: Just as a complement to Tomas' answer (which is perfectly valid), I
would like to point out that consecutive members of a struct may not be
adjacent in memory. Some structs have padding within them, which is
needed to satisfy alignment requirements.
The struct given by Tomas as an example will not have padding, but yours
may. For example, on my 64-bit PC, your struct is stored as follows:




offset
size
member




0
1
state


1
1
step


2
1
reason


3
5
(padding)


8
8
ontime


16
8
offtime




In the table above, “offset” is the position of the member relative to
the start of the struct. The padding after reason is needed in order
to align ontime at an address that is multiple of 8. Your ESP
being a 32-bit machine, it is likely to use only a single byte of
padding.
Padding may be an issue for two reasons:

It can differ between computer architectures. Thus, if you plan to
write the file on the ESP and read it back on your PC (or vice
versa), it is one of the possible sources of incompatibility, the
others being endianness and member sizes.

It is a waste of disk space, although this might not be an issue if
you are only loosing 1 byte out of 20.


If padding can be problematic, the only valid option is to write and
read the struct one member at a time. Conversely, if the file is only
ever going to be accessed by the ESP, and you don't mind loosing a few
percent of the file to padding, then don't worry, follow Tomas' advice,
and read and write the struct as an array of bytes: it is just simpler.

user61851: you can think of a struct as an array (group) of variables which might be of a different sizes and struct helps you take specific portion of this string.
Lets say you have a struct of
struct foo{
   bool first;
   uint8_t Second;
   uint16_t Third;
} structMember;

Then it is stored in a row in exactly same order as they have been defined
---------------------------
| bool | uint8_t | uint16_t|
|1 byte| 1 bytes | 2 bytes |  
--------------------------
1B+1B+2B = sizeof(srtuctMember)

File.write()
saves date in a file in block of 1Byte each.
When you send array to the function it actualy receives only  a pointer to its beginning.
That is why many functions take a size as a second argument.
When you send a data into a function in a format its not designed to take you can tell the compiler that the function should trait it as a different type of variable.
Lets say we have function defined as
void sampleFunction(byte var1)
then we can use it by
char x='j';
sampleFunction((byte) x);

which tells compiler to treat 'x' as if it was byte.
when you pass array you are not really passing the actual data, but an information where the data is(same with the struct member), so by putting asterisk after the definition you are telling compiler the format of data it points to.
and when you read it back you will get all the contend back as same data in same order... which struct then divides in a same way
file.write((byte*) &StructMember,sizeof(structMember));


48730: <p>I'm trying to store (read&amp;write( a struct using <code>LittleFS</code> on ESP8266.</p>
<p>Appreciate assistance</p>
<pre><code>struct oper_string
{
  bool state;     /* On or Off */
  uint8_t step;   /* Step, in case of PWM */
  uint8_t reason; /* What triggered the button */
  time_t ontime;  /* Start Clk */
  time_t offtime; /* Off Clk */
};
</code></pre>
 7508: <p>Just as a complement to Tomas' answer (which is perfectly valid), I
would like to point out that consecutive members of a struct may not be
adjacent in memory. Some structs have padding within them, which is
needed to satisfy <a href="https://en.wikipedia.org/wiki/Data_structure_alignment" rel="nofollow noreferrer">alignment requirements</a>.</p>
<p>The struct given by Tomas as an example will not have padding, but yours
may. For example, on my 64-bit PC, your struct is stored as follows:</p>
<div class="s-table-container">
<table class="s-table">
<thead>
<tr>
<th>offset</th>
<th>size</th>
<th style="text-align: left;">member</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>1</td>
<td style="text-align: left;">state</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td style="text-align: left;">step</td>
</tr>
<tr>
<td>2</td>
<td>1</td>
<td style="text-align: left;">reason</td>
</tr>
<tr>
<td>3</td>
<td>5</td>
<td style="text-align: left;">(padding)</td>
</tr>
<tr>
<td>8</td>
<td>8</td>
<td style="text-align: left;">ontime</td>
</tr>
<tr>
<td>16</td>
<td>8</td>
<td style="text-align: left;">offtime</td>
</tr>
</tbody>
</table>
</div>
<p>In the table above, “offset” is the position of the member relative to
the start of the struct. The padding after <code>reason</code> is needed in order
to align <code>ontime</code> at an address that is multiple of 8. Your ESP
being a 32-bit machine, it is likely to use only a single byte of
padding.</p>
<p>Padding may be an issue for two reasons:</p>
<ol>
<li><p>It can differ between computer architectures. Thus, if you plan to
write the file on the ESP and read it back on your PC (or vice
versa), it is one of the possible sources of incompatibility, the
others being endianness and member sizes.</p>
</li>
<li><p>It is a waste of disk space, although this might not be an issue if
you are only loosing 1 byte out of 20.</p>
</li>
</ol>
<p>If padding can be problematic, the only valid option is to write and
read the struct one member at a time. Conversely, if the file is only
ever going to be accessed by the ESP, and you don't mind loosing a few
percent of the file to padding, then don't worry, follow Tomas' advice,
and read and write the struct as an array of bytes: it is just simpler.</p>
 61851: <p>you can think of a struct as an array (group) of variables which might be of a different sizes and struct helps you take specific portion of this string.
Lets say you have a struct of</p>
<pre><code>struct foo{
   bool first;
   uint8_t Second;
   uint16_t Third;
} structMember;
</code></pre>
<p>Then it is stored in a row in exactly same order as they have been defined</p>
<pre><code>---------------------------
| bool | uint8_t | uint16_t|
|1 byte| 1 bytes | 2 bytes |  
--------------------------
1B+1B+2B = sizeof(srtuctMember)
</code></pre>
<p>File.write()
saves date in a file in block of 1Byte each.</p>
<p>When you send array to the function it actualy receives only  a <em><strong>pointer</strong></em> to its beginning.
That is why many functions take a size as a second argument.</p>
<p>When you send a data into a function in a format its not designed to take you can tell the compiler that the function should trait it as a different type of variable.
Lets say we have function defined as
<code>void sampleFunction(byte var1)</code>
then we can use it by</p>
<pre><code>char x='j';
sampleFunction((byte) x);
</code></pre>
<p>which tells compiler to treat 'x' as if it was <code>byte</code>.</p>
<p>when you pass array you are not really passing the actual data, but an information where the data is(same with the struct member), so by putting asterisk after the definition you are telling compiler the format of data it <em><strong>points</strong></em> to.
and when you read it back you will get all the contend back as same data in same order... which struct then divides in a same way</p>
<pre><code>file.write((byte*) &amp;StructMember,sizeof(structMember));
</code></pre>
