The UFZ::Application contains an instance of the
UFZ::Filesystem class, which is used to make interacting
with the Flipper Zero filesystem easier.
Getting a reference to the filesystem
You can get a reference to UFZ::Filesystem by calling
UFZ::Application::getFilesystem. The
Filesystem class looks like this:
class Filesystem
{
public:
FS_Error timestamp(const char* path, uint32_t* timestamp) const noexcept;
FS_Error stat(const char* path, FileInfo* fileInfo) const noexcept;
bool exists(const char* path) const noexcept;
FS_Error remove(const char* path) const noexcept;
FS_Error rename(const char* oldPath, const char* newPath) const noexcept;
FS_Error copy(const char* oldPath, const char* newPath) const noexcept;
FS_Error merge(const char* oldPath, const char* newPath) const noexcept;
FS_Error migrate(const char* source, const char* destination) const noexcept;
FS_Error mkdir(const char* path) const noexcept;
FS_Error filesystemInfo(const char* path, uint64_t* totalSpace, uint64_t* freeSpace) const noexcept;
void resolvePathAndEnsureAppDirectory(FuriString* path) const noexcept;
bool areEquivalent(const char* path1, const char* path2) const noexcept;
[[nodiscard]] static const char* getErrorDescription(FS_Error error) noexcept;
FS_Error SDCardInfo(SDInfo* info) const noexcept;
[[nodiscard]] FS_Error SDCardStatus() const noexcept;
bool removeSimple(const char* path) const noexcept;
bool removeRecursiveSimple(const char* path) const noexcept;
bool mkdirSimple(const char* path) const noexcept;
void getNextFilename(const char* dirname, const char* filename, const char* fileExtension, FuriString* nextFilename, uint8_t maxLength) const noexcept;
};The different methods correspond to the storage_* C
functions that can be found here.
Files
The UFZ::File class allows you to interact with files,
including reading and writing to them. It looks like this:
class File
{
public:
File(const UFZ::Filesystem& store, const char* path, FS_AccessMode accessMode, FS_OpenMode openMode) noexcept;
bool open(const UFZ::Filesystem& store, const char* path, FS_AccessMode accessMode, FS_OpenMode openMode) noexcept;
[[nodiscard]] bool isOpen() const noexcept;
[[nodiscard]] bool isDirectory() const noexcept;
size_t read(void* buffer, size_t bytesToRead) const noexcept;
template<typename T>
size_t read(std::vector<T>& buffer, size_t chunkSize = 128) noexcept;
size_t write(const void* buffer, size_t bytesToWrite) const noexcept;
template<typename T>
size_t write(const std::vector<T>& buffer) noexcept;
[[nodiscard]] bool seek(uint32_t offset, bool bFromStart) const noexcept;
[[nodiscard]] uint64_t tell() const noexcept;
[[nodiscard]] bool truncate() const noexcept;
[[nodiscard]] uint64_t size() const noexcept;
[[nodiscard]] bool sync() const noexcept;
[[nodiscard]] bool eof() const noexcept;
static bool copyToFile(const File& source, const File& destination, size_t size) noexcept;
void close() noexcept;
~File() noexcept;
};The functions are self-explanatory in what they do. For further
documentation, refer to storage_file_* C functions on
the flipper docs.
Note
When reading, make sure you're managing your memory correctly, as running out of memory is not an uncommon occurrence on large files.
Directories
Similar to UFZ::File, the UFZ::Directory
class allows you to interact with directories. It looks like this:
class Directory
{
public:
bool open(File& f, const char* path) noexcept;
[[nodiscard]] bool close() const noexcept;
bool read(FileInfo* info, char* name, uint16_t nameLength) const noexcept;
[[nodiscard]] bool rewind() const noexcept;
};Reading on a directory allows you to iterate its contents.