Y a-t-il des pièges pour des systèmes d'exploitation spécifiques, que je devrais connaître?
Il existe de nombreux doublons ( 1 , 2 , , 4 , 5 ) de cette question, mais ils ont été répondu il y a des décennies. Les réponses très votées dans bon nombre de ces questions sont erronées aujourd'hui.
stat.h (wrapper sprintstatf ), utilise syscall
tellg () , renvoie par définition une position mais pas nécessairement des octets . Le type de retour n'est pas int
.
<filesystem>
(ajouté en C++ 17) rend cela très simple .
#include <cstdint>
#include <filesystem>
// ...
std::uintmax_t size = std::filesystem::file_size("c:\\foo\\bar.txt");
Comme indiqué dans les commentaires, si vous prévoyez d'utiliser cette fonction pour décider du nombre d'octets à lire dans le fichier, gardez à l'esprit que ...
... sauf si le fichier est ouvert exclusivement par vous, sa taille peut être modifiée entre le moment où vous le demandez et le moment où vous essayez de lire les données.
- Nicol Bolas
C++ 17 apporte std::filesystem
qui rationalise de nombreuses tâches sur les fichiers et les répertoires. Non seulement vous pouvez obtenir rapidement la taille du fichier, ses attributs, mais aussi créer de nouveaux répertoires, parcourir les fichiers, travailler avec des objets de chemin.
La nouvelle bibliothèque nous donne deux fonctions que nous pouvons utiliser:
std::uintmax_t std::filesystem::file_size( const std::filesystem::path& p );
std::uintmax_t std::filesystem::directory_entry::file_size() const;
La première fonction est une fonction libre dans std::filesystem
, la seconde est une méthode dans directory_entry
.
Chaque méthode a également une surcharge, car elle peut lever une exception ou retourner un code d'erreur (via un paramètre de sortie). Vous trouverez ci-dessous le code détaillé expliquant tous les cas possibles.
#include <chrono>
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
int main(int argc, char* argv[])
{
try
{
const auto fsize = fs::file_size("a.out");
std::cout << fsize << '\n';
}
catch (const fs::filesystem_error& err)
{
std::cerr << "filesystem error! " << err.what() << '\n';
if (!err.path1().empty())
std::cerr << "path1: " << err.path1().string() << '\n';
if (!err.path2().empty())
std::cerr << "path2: " << err.path2().string() << '\n';
}
catch (const std::exception& ex)
{
std::cerr << "general exception: " << ex.what() << '\n';
}
// using error_code
std::error_code ec{};
auto size = std::filesystem::file_size("a.out", ec);
if (ec == std::error_code{})
std::cout << "size: " << size << '\n';
else
std::cout << "error when accessing test file, size is: "
<< size << " message: " << ec.message() << '\n';
}