web-dev-qa-db-fra.com

Comment obtenir la taille du fichier en octets avec C ++ 17

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.

Méthodes d'autres (anciens QA) sur .sx

  • 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.

93
Jonas Stein

<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

119
HolyBlackCat

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';
}
27
GOVIND DIXIT