In this guide, you’ll learn how to write and save data permanently to a file saved on the ESP32 filesystem (LittleFS). LittleFS is a lightweight filesystem created for microcontrollers that lets you access the flash memory like you would do in a standard file system on your computer, but simple and more limited.
![ESP32: Write Data to a File (LittleFS) - Arduino | Random Nerd Tutorials (1) ESP32: Write Data to a File (LittleFS) - Arduino | Random Nerd Tutorials (1)](https://i0.wp.com/i0.wp.com/randomnerdtutorials.com/wp-content/uploads/2023/07/ESP32-Write-Data-To-a-File-LittleFS.jpg?resize=828%2C466&quality=100&strip=all&ssl=1)
We have a similar tutorial for ESP8266 boards: ESP8266 NodeMCU: Write Data to a File (LittleFS) – Arduino IDE.
Table of Contents
Throughout this tutorial, we’ll cover the following topics:
- Introducing LittleFS
- ESP32 with LittleFS – Handling Files and Folders
- ESP32 with LittleFS – How to Save Variables’ Values to a File
- ESP32 with LittleFS – Check if a file already exists
Prerequisites
We’ll program the ESP32 board using Arduino IDE. So, make sure you have the ESP32 add-on installed. Follow the next tutorial if you haven’t already:
- Install the ESP32 Board in Arduino IDE
Additionally, make sure you’re running the latest version of the ESP32 add-on. Go to Tools > Board > Boards Manager, search for ESP32, and check that you’re running the latest version.
Introducing LittleFS
LittleFS is a lightweight filesystem created for microcontrollers that lets you access the flash memory like you would do in a standard file system on your computer, but it’s simpler and more limited. You can read, write, close, and delete files and folders. Using a filesystem with the ESP32 boards is especially useful to:
- Create configuration files with settings;
- Save data permanently;
- Create files to save small amounts of data instead of using a microSD card;
- Save HTML, CSS, and JavaScript files to build a web server;
- Save images, figures, and icons;
- And much more.
You may also like reading: ESP32: Upload Files to LittleFS using Arduino IDE.
ESP32 with LittleFS – Handling Files and Folders
Before showing you how to write data to a file on LittleFS with the ESP32, let’s take a look at an example that shows how to do practically any task that you may need when dealing with files and folders.
The following code was adapted from the official example.
// Adapted from: https://github.com/espressif/arduino-esp32/blob/master/libraries/LittleFS/examples/LITTLEFS_test/LITTLEFS_test.ino// Project details: https://RandomNerdTutorials.com/esp32-write-data-littlefs-arduino/#include <Arduino.h>#include "FS.h"#include <LittleFS.h>// You only need to format LittleFS the first time you run a// test or else use the LITTLEFS plugin to create a partition // https://github.com/lorol/arduino-esp32littlefs-plugin#define FORMAT_LITTLEFS_IF_FAILED truevoid listDir(fs::FS &fs, const char * dirname, uint8_t levels){ Serial.printf("Listing directory: %s\r\n", dirname); File root = fs.open(dirname); if(!root){ Serial.println("- failed to open directory"); return; } if(!root.isDirectory()){ Serial.println(" - not a directory"); return; } File file = root.openNextFile(); while(file){ if(file.isDirectory()){ Serial.print(" DIR : "); Serial.println(file.name()); if(levels){ listDir(fs, file.path(), levels -1); } } else { Serial.print(" FILE: "); Serial.print(file.name()); Serial.print("\tSIZE: "); Serial.println(file.size()); } file = root.openNextFile(); }}void createDir(fs::FS &fs, const char * path){ Serial.printf("Creating Dir: %s\n", path); if(fs.mkdir(path)){ Serial.println("Dir created"); } else { Serial.println("mkdir failed"); }}void removeDir(fs::FS &fs, const char * path){ Serial.printf("Removing Dir: %s\n", path); if(fs.rmdir(path)){ Serial.println("Dir removed"); } else { Serial.println("rmdir failed"); }}void readFile(fs::FS &fs, const char * path){ Serial.printf("Reading file: %s\r\n", path); File file = fs.open(path); if(!file || file.isDirectory()){ Serial.println("- failed to open file for reading"); return; } Serial.println("- read from file:"); while(file.available()){ Serial.write(file.read()); } file.close();}void writeFile(fs::FS &fs, const char * path, const char * message){ Serial.printf("Writing file: %s\r\n", path); File file = fs.open(path, FILE_WRITE); if(!file){ Serial.println("- failed to open file for writing"); return; } if(file.print(message)){ Serial.println("- file written"); } else { Serial.println("- write failed"); } file.close();}void appendFile(fs::FS &fs, const char * path, const char * message){ Serial.printf("Appending to file: %s\r\n", path); File file = fs.open(path, FILE_APPEND); if(!file){ Serial.println("- failed to open file for appending"); return; } if(file.print(message)){ Serial.println("- message appended"); } else { Serial.println("- append failed"); } file.close();}void renameFile(fs::FS &fs, const char * path1, const char * path2){ Serial.printf("Renaming file %s to %s\r\n", path1, path2); if (fs.rename(path1, path2)) { Serial.println("- file renamed"); } else { Serial.println("- rename failed"); }}void deleteFile(fs::FS &fs, const char * path){ Serial.printf("Deleting file: %s\r\n", path); if(fs.remove(path)){ Serial.println("- file deleted"); } else { Serial.println("- delete failed"); }}void testFileIO(fs::FS &fs, const char * path){ Serial.printf("Testing file I/O with %s\r\n", path); static uint8_t buf[512]; size_t len = 0; File file = fs.open(path, FILE_WRITE); if(!file){ Serial.println("- failed to open file for writing"); return; } size_t i; Serial.print("- writing" ); uint32_t start = millis(); for(i=0; i<2048; i++){ if ((i & 0x001F) == 0x001F){ Serial.print("."); } file.write(buf, 512); } Serial.println(""); uint32_t end = millis() - start; Serial.printf(" - %u bytes written in %u ms\r\n", 2048 * 512, end); file.close(); file = fs.open(path); start = millis(); end = start; i = 0; if(file && !file.isDirectory()){ len = file.size(); size_t flen = len; start = millis(); Serial.print("- reading" ); while(len){ size_t toRead = len; if(toRead > 512){ toRead = 512; } file.read(buf, toRead); if ((i++ & 0x001F) == 0x001F){ Serial.print("."); } len -= toRead; } Serial.println(""); end = millis() - start; Serial.printf("- %u bytes read in %u ms\r\n", flen, end); file.close(); } else { Serial.println("- failed to open file for reading"); }}void setup(){ Serial.begin(115200); if(!LittleFS.begin(FORMAT_LITTLEFS_IF_FAILED)){ Serial.println("LittleFS Mount Failed"); return; } createDir(LittleFS, "/mydir"); // Create a mydir folder writeFile(LittleFS, "/mydir/hello1.txt", "Hello1"); // Create a hello1.txt file with the content "Hello1" listDir(LittleFS, "/", 1); // List the directories up to one level beginning at the root directory deleteFile(LittleFS, "/mydir/hello1.txt"); //delete the previously created file removeDir(LittleFS, "/mydir"); //delete the previously created folder listDir(LittleFS, "/", 1); // list all directories to make sure they were deleted writeFile(LittleFS, "/hello.txt", "Hello "); //Create and write a new file in the root directory appendFile(LittleFS, "/hello.txt", "World!\r\n"); //Append some text to the previous file readFile(LittleFS, "/hello.txt"); // Read the complete file renameFile(LittleFS, "/hello.txt", "/foo.txt"); //Rename the previous file readFile(LittleFS, "/foo.txt"); //Read the file with the new name deleteFile(LittleFS, "/foo.txt"); //Delete the file testFileIO(LittleFS, "/test.txt"); //Testin deleteFile(LittleFS, "/test.txt"); //Delete the file Serial.println( "Test complete" ); }void loop(){}
This code covers the following:
- List a directory;
- Create a directory;
- Remove a directory;
- Read a file’s content;
- Write content to a file;
- Append content to a file;
- Rename a file;
- Delete a file;
- Initialize the LittleFS filesystem.
How the Code Works
First, you need to include the following libraries: FS.h to handle files, and LittleFS.h to create and access the filesystem.
#include "FS.h"#include <LittleFS.h>
The first time you use LittleFS on the ESP32, you need to format it so that it creates a partition dedicated to that filesystem. To do that, we have the following boolean variable to control whether we want to format the filesystem or not.
#define FORMAT_LITTLEFS_IF_FAILED true
The example provides several functions to handle files on the LittleFS filesystem. Let’s take a look at them.
List a directory
The listDir() function lists the directories on the filesystem. This function accepts as arguments the filesystem (LittleFs), the main directory’s name, and the levels to go into the directory.
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){ Serial.printf("Listing directory: %s\r\n", dirname); File root = fs.open(dirname); if(!root){ Serial.println("- failed to open directory"); return; } if(!root.isDirectory()){ Serial.println(" - not a directory"); return; } File file = root.openNextFile(); while(file){ if(file.isDirectory()){ Serial.print(" DIR : "); Serial.println(file.name()); if(levels){ listDir(fs, file.path(), levels -1); } } else { Serial.print(" FILE: "); Serial.print(file.name()); Serial.print("\tSIZE: "); Serial.println(file.size()); } file = root.openNextFile(); }}
Here’s an example of how to call this function. The / corresponds to the root directory. The following command will list all the directories up to one level beginning at the root directory.
listDir(LittleFS, "/", 1); // List the directories up to one level beginning at the root directory
Create a Directory
The createDir() function creates a new directory. Pass as an argument the LittleFS filesystem and the directory name path.
void createDir(fs::FS &fs, const char * path){ Serial.printf("Creating Dir: %s\n", path); if(fs.mkdir(path)){ Serial.println("Dir created"); } else { Serial.println("mkdir failed"); }}
For example, the following command creates a new directory (folder) on the root called mydir.
createDir(LittleFS, "/mydir"); // Create a mydir folder
Remove a Directory
To remove a directory from the filesystemca, use the removeDir() function and pass as an argument the LittleFS filesystem and the directory name path.
void removeDir(fs::FS &fs, const char * path){ Serial.printf("Removing Dir: %s\n", path); if(fs.rmdir(path)){ Serial.println("Dir removed"); } else { Serial.println("rmdir failed"); }}
Here is an example that deletes the mydir folder.
removeDir(LittleFS, "/mydir");
Read File Content
The readFile() function reads the content of a file and prints the content in the Serial Monitor. As with previous functions, pass as an argument the LittleFs filesystem and the file path.
void readFile(fs::FS &fs, const char * path){ Serial.printf("Reading file: %s\r\n", path); File file = fs.open(path); if(!file || file.isDirectory()){ Serial.println("- failed to open file for reading"); return; } Serial.println("- read from file:"); while(file.available()){ Serial.write(file.read()); } file.close();}
For example, the following line reads the content of the hello.txt file.
readFile(LittleFS, "/hello.txt"); // Read the complete file
Write Content to a File
To write content to a file, you can use the writeFile() function. Pass as an argument, the LittleFS filesystem, the file path, and the message (as a const char variable).
void writeFile(fs::FS &fs, const char * path, const char * message){ Serial.printf("Writing file: %s\r\n", path); File file = fs.open(path, FILE_WRITE); if(!file){ Serial.println("- failed to open file for writing"); return; } if(file.print(message)){ Serial.println("- file written"); } else { Serial.println("- write failed"); } file.close();}
The following line writes Hello in the hello.txt file.
writeFile(LittleFS, "/hello.txt", "Hello ");
Append Content to a File
Similarly, you can append content to a file (without overwriting previous content) using the appendFile() function.
void appendFile(fs::FS &fs, const char * path, const char * message){ Serial.printf("Appending to file: %s\r\n", path); File file = fs.open(path, FILE_APPEND); if(!file){ Serial.println("- failed to open file for appending"); return; } if(file.print(message)){ Serial.println("- message appended"); } else { Serial.println("- append failed"); } file.close();}
The following line appends the message World!\r\n in the hello.txt file. The \r\n means that the next time you write something to the file, it will be written in a new line.
appendFile(LittleFS, "/hello.txt", "World!\r\n");
Rename a File
You can rename a file using the renameFile() function. Pass as arguments the LittleFS filesystem, the original filename, and the new filename.
void renameFile(fs::FS &fs, const char * path1, const char * path2){ Serial.printf("Renaming file %s to %s\r\n", path1, path2); if (fs.rename(path1, path2)) { Serial.println("- file renamed"); } else { Serial.println("- rename failed"); }}
The following line renames the hello.txt file to foo.txt.
renameFile(LittleFS, "/hello.txt", "/foo.txt");
Delete a File
Use the deleteFile() function to delete a file. Pass as an argument the LittleFS filesystem and the file path of the file you want to delete.
void deleteFile(fs::FS &fs, const char * path){ Serial.printf("Deleting file: %s\r\n", path); if(fs.remove(path)){ Serial.println("- file deleted"); } else { Serial.println("- delete failed"); }}
The following line deletes the foo.txt file from the filesystem.
deleteFile(LittleFS, "/foo.txt");
Test a File
The testFileIO() function shows how long it takes to read the content of a file.
void testFileIO(fs::FS &fs, const char * path){ Serial.printf("Testing file I/O with %s\r\n", path); static uint8_t buf[512]; size_t len = 0; File file = fs.open(path, FILE_WRITE); if(!file){ Serial.println("- failed to open file for writing"); return; } size_t i; Serial.print("- writing" ); uint32_t start = millis(); for(i=0; i<2048; i++){ if ((i & 0x001F) == 0x001F){ Serial.print("."); } file.write(buf, 512); } Serial.println(""); uint32_t end = millis() - start; Serial.printf(" - %u bytes written in %u ms\r\n", 2048 * 512, end); file.close(); file = fs.open(path); start = millis(); end = start; i = 0; if(file && !file.isDirectory()){ len = file.size(); size_t flen = len; start = millis(); Serial.print("- reading" ); while(len){ size_t toRead = len; if(toRead > 512){ toRead = 512; } file.read(buf, toRead); if ((i++ & 0x001F) == 0x001F){ Serial.print("."); } len -= toRead; } Serial.println(""); end = millis() - start; Serial.printf("- %u bytes read in %u ms\r\n", flen, end); file.close(); } else { Serial.println("- failed to open file for reading"); }}
The following function tests the test.txt file.
testFileIO(LittleFS, "/test.txt");
Initialize the Filesystem
In the setup(), the following lines initialize the LittleFS filesystem.
if(!LittleFS.begin(FORMAT_LITTLEFS_IF_FAILED)){ Serial.println("LittleFS Mount Failed"); return;}
The LittleFS.begin() function returns true if the filesystem is initialized successfully or false if it isn’t.
You can pass true or false as an argument to the begin() method. If you pass true it will format the LittleFS filesystem if the initialization fails. Because this is the first test we’re running, we set the FORMAT_LITTLEFS_IF_FAILED variable to true.
Testing the Filesystem
The following lines call all the functions we’ve seen previously.
createDir(LittleFS, "/mydir"); // Create a mydir folderwriteFile(LittleFS, "/mydir/hello1.txt", "Hello1"); // Create a hello1.txt file with the content "Hello1"listDir(LittleFS, "/", 1); // List the directories up to one level beginning at the root directorydeleteFile(LittleFS, "/mydir/hello1.txt"); //delete the previously created fileremoveDir(LittleFS, "/mydir"); //delete the previously created folderlistDir(LittleFS, "/", 1); // list all directories to make sure they were deleted writeFile(LittleFS, "/hello.txt", "Hello "); //Create and write a new file in the root directoryappendFile(LittleFS, "/hello.txt", "World!\r\n"); //Append some text to the previous filereadFile(LittleFS, "/hello.txt"); // Read the complete filerenameFile(LittleFS, "/hello.txt", "/foo.txt"); //Rename the previous filereadFile(LittleFS, "/foo.txt"); //Read the file with the new namedeleteFile(LittleFS, "/foo.txt"); //Delete the filetestFileIO(LittleFS, "/test.txt"); //TestindeleteFile(LittleFS, "/test.txt"); //Delete the file
Demonstration
Upload the previous sketch to your ESP32 board. After that, open the Serial Monitor and press the ESP32 on-board RST button. If the initialization succeeds, you’ll get similar messages on the Serial Monitor.
![ESP32: Write Data to a File (LittleFS) - Arduino | Random Nerd Tutorials (2) ESP32: Write Data to a File (LittleFS) - Arduino | Random Nerd Tutorials (2)](https://i0.wp.com/i0.wp.com/randomnerdtutorials.com/wp-content/uploads/2023/07/testing-Little-FS-Serial-Monitor.png?resize=601%2C791&quality=100&strip=all&ssl=1)
ESP32 with LittleFS – How to Save Variables’ Values to a File
The previous example illustrated almost all the operations you might need to do when dealing with files and folders on the filesystem. In this section, we’ll take a look at a more simple and specific example: how to save the content of a variable to the filesystem.
Let’s take a look at the following code.
// Project details: https://RandomNerdTutorials.com/esp32-write-data-littlefs-arduino/#include <Arduino.h>#include "FS.h"#include <LittleFS.h>#define FORMAT_LITTLEFS_IF_FAILED trueint mydata;void writeFile(fs::FS &fs, const char * path, const char * message){ Serial.printf("Writing file: %s\r\n", path); File file = fs.open(path, FILE_WRITE); if(!file){ Serial.println("- failed to open file for writing"); return; } if(file.print(message)){ Serial.println("- file written"); } else { Serial.println("- write failed"); } file.close();}void appendFile(fs::FS &fs, const char * path, const char * message){ Serial.printf("Appending to file: %s\r\n", path); File file = fs.open(path, FILE_APPEND); if(!file){ Serial.println("- failed to open file for appending"); return; } if(file.print(message)){ Serial.println("- message appended"); } else { Serial.println("- append failed"); } file.close();}void readFile(fs::FS &fs, const char * path){ Serial.printf("Reading file: %s\r\n", path); File file = fs.open(path); if(!file || file.isDirectory()){ Serial.println("- failed to open file for reading"); return; } Serial.println("- read from file:"); while(file.available()){ Serial.write(file.read()); } file.close();}void setup() { Serial.begin(115200); if(!LittleFS.begin(FORMAT_LITTLEFS_IF_FAILED)){ Serial.println("LittleFS Mount Failed"); return; } else{ Serial.println("Little FS Mounted Successfully"); } writeFile(LittleFS, "/data.txt", "MY ESP32 DATA \r\n");}void loop() { mydata = random (0, 1000); appendFile(LittleFS, "/data.txt", (String(mydata)+ "\r\n").c_str()); //Append data to the file readFile(LittleFS, "/data.txt"); // Read the contents of the file delay(30000);}
For this example, we’ll continuously save the value of a variable to the filesystem. As an example, we’ll save a random number, but this can be easily adjusted to save sensor readings, for example.
We start by creating a variable that will hold the random number called mydata.
int mydata;
For this particular example, we just need to use the writeFile(), appendFile(), and readFile() functions. So, we have those functions defined before the setup():
void writeFile(fs::FS &fs, const char * path, const char * message){ Serial.printf("Writing file: %s\r\n", path); File file = fs.open(path, FILE_WRITE); if(!file){ Serial.println("- failed to open file for writing"); return; } if(file.print(message)){ Serial.println("- file written"); } else { Serial.println("- write failed"); } file.close();}void appendFile(fs::FS &fs, const char * path, const char * message){ Serial.printf("Appending to file: %s\r\n", path); File file = fs.open(path, FILE_APPEND); if(!file){ Serial.println("- failed to open file for appending"); return; } if(file.print(message)){ Serial.println("- message appended"); } else { Serial.println("- append failed"); } file.close();}void readFile(fs::FS &fs, const char * path){ Serial.printf("Reading file: %s\r\n", path); File file = fs.open(path); if(!file || file.isDirectory()){ Serial.println("- failed to open file for reading"); return; } Serial.println("- read from file:"); while(file.available()){ Serial.write(file.read()); } file.close();}
In the setup(), we initialize the Serial Monitor for debugging purposes.
Serial.begin(115200);
And we initialize the LittleFS filesystem:
if(!LittleFS.begin(FORMAT_LITTLEFS_IF_FAILED)){ Serial.println("LittleFS Mount Failed"); return;}else{ Serial.println("Little FS Mounted Successfully");}
Then, we create a file called data.txt with the following text inside MY ESP32 DATA:
writeFile(LittleFS, "/data.txt", "MY ESP32 DATA \r\n");
Something to notice about the writeFile() function: it creates a file (if it doesn’t exist) called data.txt with the text we define inside.
If that file already exists, the writeFile() function will overwrite any existing contents inside that file. So, if you want to continuously add new data without replacing it, you should use the appendFile() function after creating the file. If you want to replace the content of the file, you should use the writeFile().
In the loop(), we start by attributing a random value between 0 and 1000 to the mydata variable.
mydata = random (0, 1000);
Then, we append data to the file by calling the appendFile() function.
appendFile(LittleFS, "/data.txt", (String(mydata)+ "\r\n").c_str()); //Append data to the file
Notice that we concatenate the mydata variable with “\r\n” so that subsequent data is written on the next line. Because our variable is of int type, we need to convert it to a String before concatenating.
String(mydata)
Additionally, then, we need to convert it to a const char using the c_str() method:
String(mydata)+ "\r\n").c_str()
After appending data to the file, we’ll read its content by calling the readFile() function.
readFile(LittleFS, "/data.txt"); // Read the contents of the file
New random values are generated and added to the file every 30 seconds.
delay(30000);
Demonstration
Upload the code to your ESP32 board. Open the Serial Monitor at a baud rate of 115200.
It should initialize the filesystem, create the file and start adding a new random number to the file every 30 seconds.
![ESP32: Write Data to a File (LittleFS) - Arduino | Random Nerd Tutorials (3) ESP32: Write Data to a File (LittleFS) - Arduino | Random Nerd Tutorials (3)](https://i0.wp.com/i0.wp.com/randomnerdtutorials.com/wp-content/uploads/2023/07/ESP32-LittleFS-Append-Data.png?resize=601%2C732&quality=100&strip=all&ssl=1)
Notice that if you restart your board, you’ll lose all your previous data. Why is that happening?
![ESP32: Write Data to a File (LittleFS) - Arduino | Random Nerd Tutorials (4) ESP32: Write Data to a File (LittleFS) - Arduino | Random Nerd Tutorials (4)](https://i0.wp.com/i0.wp.com/randomnerdtutorials.com/wp-content/uploads/2023/07/ESP32-LittleFS-Append-Data-restart.png?resize=601%2C732&quality=100&strip=all&ssl=1)
That happens because we’re calling the writeFile() function in the setup(). As we’ve explained previously, it will create a new file if it doesn’t exist, or overwrite an already existing file with the same name. To prevent that, we can add some lines to the setup() to check whether the file already exists.
ESP32 with LittleFS – Check if a file already exists
To check if a file already exists in the filesystem, we can use the exists() method and pass as an argument the file path. You can add the following lines to the setup() to prevent overwriting when the ESP32 restarts:
// Check if the file already exists to prevent overwritting existing databool fileexists = LittleFS.exists("/data.txt");Serial.print(fileexists);if(!fileexists) { Serial.println("File doesn’t exist"); Serial.println("Creating file..."); // Create File and add header writeFile(LittleFS, "/data.txt", "MY ESP32 DATA \r\n");}else { Serial.println("File already exists");}
It uses the exists() method to check if the file already exists:
bool fileexists = LittleFS.exists("/data.txt");
It will return true if the file already exists or false if it doesn’t.
If it doesn’t exist, it will create the file with the content with define.
if(!fileexists) { Serial.println("File doesn’t exist"); Serial.println("Creating file..."); // Create File and add header writeFile(LittleFS, "/data.txt", "MY ESP32 DATA \r\n");}
If it already exists, it simply writes File already exists in the Serial Monitor.
else { Serial.println("File already exists");}
Here’s the complete example that checks if the file already exists.
// Project details: https://RandomNerdTutorials.com/esp32-write-data-littlefs-arduino/#include <Arduino.h>#include "FS.h"#include <LittleFS.h>/* You only need to format LittleFS the first time you run a test or else use the LITTLEFS plugin to create a partition https://github.com/lorol/arduino-esp32littlefs-plugin */#define FORMAT_LITTLEFS_IF_FAILED trueint mydata;void writeFile(fs::FS &fs, const char * path, const char * message){ Serial.printf("Writing file: %s\r\n", path); File file = fs.open(path, FILE_WRITE); if(!file){ Serial.println("- failed to open file for writing"); return; } if(file.print(message)){ Serial.println("- file written"); } else { Serial.println("- write failed"); } file.close();}void appendFile(fs::FS &fs, const char * path, const char * message){ Serial.printf("Appending to file: %s\r\n", path); File file = fs.open(path, FILE_APPEND); if(!file){ Serial.println("- failed to open file for appending"); return; } if(file.print(message)){ Serial.println("- message appended"); } else { Serial.println("- append failed"); } file.close();}void readFile(fs::FS &fs, const char * path){ Serial.printf("Reading file: %s\r\n", path); File file = fs.open(path); if(!file || file.isDirectory()){ Serial.println("- failed to open file for reading"); return; } Serial.println("- read from file:"); while(file.available()){ Serial.write(file.read()); } file.close();}void setup() { Serial.begin(115200); if(!LittleFS.begin(FORMAT_LITTLEFS_IF_FAILED)){ Serial.println("LittleFS Mount Failed"); return; } else{ Serial.println("Little FS Mounted Successfully"); } // Check if the file already exists to prevent overwritting existing data bool fileexists = LittleFS.exists("/data.txt"); Serial.print(fileexists); if(!fileexists) { Serial.println("File doesn’t exist"); Serial.println("Creating file..."); // Create File and add header writeFile(LittleFS, "/data.txt", "MY ESP32 DATA \r\n"); } else { Serial.println("File already exists"); }}void loop() { mydata = random (0, 1000); appendFile(LittleFS, "/data.txt", (String(mydata)+ "\r\n").c_str()); //Append data to the file readFile(LittleFS, "/data.txt"); // Read the contents of the file delay(30000);}
If you test this example, you’ll see that the file keeps all data even after a restart.
![ESP32: Write Data to a File (LittleFS) - Arduino | Random Nerd Tutorials (5) ESP32: Write Data to a File (LittleFS) - Arduino | Random Nerd Tutorials (5)](https://i0.wp.com/i0.wp.com/randomnerdtutorials.com/wp-content/uploads/2023/07/ESP32-LittleFS-Save-Data-Prevent-Overwrite.png?resize=601%2C755&quality=100&strip=all&ssl=1)
Wrapping Up
With this tutorial, you learned how to save data permanently on a file in the ESP32 LittleFS filesystem. You learn how to create a file, append data, and read the contents of a file.
If you have a file with content that you want to save to the ESP32, and you don’t need to add data during runtime, you may want to use the LittleFS plugin instead. It allows you to save files that you have on your sketch folder directly to the ESP32 filesystem: ESP32: Upload Files to LittleFS using Arduino IDE.
We hope you found this tutorial useful. Learn more about the ESP32 with our resources:
- Learn ESP32 with Arduino IDE (eBook)
- Build Web Servers with ESP32 and ESP8266 (eBook)
- Firebase Web App with ESP32 and ESP8266 (eBook)
- Free ESP32 Projects and Tutorials