-
Notifications
You must be signed in to change notification settings - Fork 0
File
ML::File is a set of cross-platform file and folder utilities built on
std::filesystem. Errors are reported to std::cerr; query methods return sensible
defaults on failure. Every method takes plain std::string paths.
void createFolder(std::string name); // single level
void createFolders(std::string path); // recursive (mkdir -p)
void createFile(std::string name, std::string content); // create or overwrite
void appendFile(std::string name, std::string content); // append to the end
void writeBytes(std::string name, const std::vector<unsigned char>& data); // binaryvoid writeFileAtomic(std::string name, std::string content);
void writeBytesAtomic(std::string name, const std::vector<unsigned char>& data);Both methods stage the data in a temporary file next to the target, then rename over it. If the process crashes partway through, the existing target file is untouched. The temp is created in the same directory as the target so the rename stays a real atomic rename instead of a cross-filesystem copy. Reach for these when a partially written file would corrupt something the user or another process reads later, like a save file or a config file.
std::string readFile(std::string name); // text, line-based
std::string readAll(std::string name); // exact bytes (binary-safe)
std::vector<unsigned char> readBytes(std::string name); // raw bytesreadAll keeps the file's exact bytes with no whitespace mangling, so it is the right
choice for JSON, binary, or anything where exact content matters.
std::vector<std::string> readLines(std::string name);
void writeLines(std::string name, const std::vector<std::string>& lines);readLines splits on \n and drops the empty string that a trailing newline would
produce, so a file that ends with \n does not add a phantom empty line at the end.
A stray \r from CRLF line endings is stripped from each line, so a file authored on
Windows reads back the same as one authored on Linux.
writeLines joins with \n and adds a final newline so the file is well-formed for
POSIX tools. Round-tripping a file that contains no \r or \n inside its lines is
lossless.
void deleteFile(std::string name);
void deleteFolder(std::string name); // recursive
void copyFile(std::string src, std::string dst); // overwrites dst
void moveFile(std::string src, std::string dst); // rename or movestd::vector<std::string> listFiles(std::string folder); // names, one level deep
std::vector<std::string> listFilesRecursive(std::string folder); // all files, recursivelistFiles returns the names directly inside a folder. listFilesRecursive walks the
whole tree and returns every file as a path relative to the folder, using forward slashes
(for example images/birds/downflap.png). It lists files only, not directories, and
returns an empty list if the folder is missing.
Both methods have overloads that filter by a shell-style glob pattern:
std::vector<std::string> listFiles(std::string folder, std::string pattern);
std::vector<std::string> listFilesRecursive(std::string folder, std::string pattern);The pattern matches file basenames, not full paths. * matches any run of characters,
? matches exactly one, and [abc] matches any character in the set (use [!abc] to
negate). Everything else is literal, including ., so *.png matches every PNG in the
folder and file.name.txt matches only that exact filename.
bool exists(std::string name);
bool isFile(std::string name);
bool isDirectory(std::string name);
int fileCharacterCount(std::string name);
long fileSize(std::string name); // bytes, -1 if missing
long long lastModified(std::string name); // unix seconds, -1 if missingstd::string makeTempFile(std::string prefix = "fileml");
std::string makeTempDir(std::string prefix = "fileml");Both create a fresh entry under the system temp directory (whatever
std::filesystem::temp_directory_path() returns on the platform) and hand back the
full path. The prefix is prepended to a random suffix so the name is easy to spot
while staying unique. The caller owns cleanup; nothing is auto-deleted.
File f;
f.createFolders("data/cache");
f.createFile("data/note.txt", "hello");
f.appendFile("data/note.txt", " world");
std::cout << f.readAll("data/note.txt"); // "hello world"
std::cout << f.fileSize("data/note.txt"); // 11
for (const auto& name : f.listFiles("data"))
std::cout << name << "\n";
// every file under a tree, as relative paths
for (const auto& path : f.listFilesRecursive("data"))
std::cout << path << "\n";
// find just the PNGs, at any depth
for (const auto& png : f.listFilesRecursive("data", "*.png"))
std::cout << png << "\n";
// binary read and write
auto bytes = f.readBytes("image.png");
f.writeBytes("copy.png", bytes);
// atomic write for something worth protecting
f.writeFileAtomic("save.json", R"({"score":1234})");