SdFat: When to call sync()

A dumb question:

When using write() and print() it is necessary to call sync() in order to commit more than just the latest data block to the SD card. In the example sketches I've looked at, sync() is called very frequently. I want to minimize I/O and I believe sync needs to be called after 512 bytes are written. But I can't figure out what the intended approach for doing this is exactly.

Simple example:

loop() {
  getData();

  file.write(dataX);
  file.print(dataY);
  file.print(somethingElse);
  file.write(anotherItem);
  file.print(dataZ,3);
  file.write(stuff);

  if ( ? )
    file.sync();
}

You don't need to call sync(). You only need to close a file that is open for write. Closing the file forces any buffered data to be written to the SD and also updates the file's directory entry.

If you don't close the file, you will lose all data written the file since it was opened, not just the last buffer, since the directory entry will not be updated.

Calling sync() is equivalent to closing the file and then reopening the file but much faster. Many data logging examples actually repeatedly open a file, write a little data, then close the file. This is very inefficient.

The main reason to call sync is to insure you will lose a limited amount of data in case of a crash or power failure.

Thanks for making it so clear. The documentation says what you just did but somehow I ended up with a different picture in my mind.

Actually, I got the idea from the documentation. It's a little misleading when it says one "must" call sync().

I also ran across a post where you stated:

The Arduino Print class has been implemented in a way that

  • causes a call to the SdFat write function for every byte when*
  • formatting a number.*

That doesn't seem to be the case anymore.

The Arduino Print class has been implemented in a way that
causes a call to the SdFat write function for every byte when
formatting a number.

That doesn't seem to be the case anymore.

Yes, Print now uses an optimized function I developed. I was amazed when the Arduino company adopted my version of Print::printNumber().

Unfortunately, the function
size_t Print::write(const uint8_t *buffer, size_t size)
is not pure virtual in the Print class. SdFat implemented write as the more general

int SdFile::write(const void* buf, size_t nbyte);

This function does not override the Print's virtual write and print was character at a time for a while in Sdfat after my mod to print was adopted.

SdFile now has this additional function which causes the optimized version of Print::printNumber() to work.

  size_t SdFile::write(const uint8_t *buf, size_t size) {
    return SdBaseFile::write(buf, size);
  }