C ++ 17でファイルサイズをバイト単位で取得する方法


97

特定のオペレーティングシステムの落とし穴はありますか。

そこに多くの重複(ある12345、この質問のは)しかし、彼らは数十年前に答えました。これらの質問の多くで投票数が非常に多い回答は、今日間違っています。

.sxでの他の(古いQAの)メソッド

  • stat.h(ラッパーsprintstatf)、syscallを使用

  • tellg()は、定義ごとに位置を返しますが、必ずしもバイトではありません。戻り値の型はではありませんint



5
@LF:さて、最初の質問は2番目の質問の複製としてクローズされました。これは、最初の質問で受け入れられた回答が間違っている理由を説明してます。3つ目は、同様のtellg問題について尋ねています。気になるのは4番目ofstreamの質問だけです。質問とその回答の両方でについて語りすぎているため、これは素晴らしいものではありません。これは他のものよりも意図を表現するのにはるかに優れています(奇妙に閉じられている最初のものを除いて)。
Nicol Bolas

6
質問や質問のタイトルに無関係な情報を追加するのをやめてください。年は無関係です。テクノロジーが関連しています。
エリクセニド

2
stat(2)とにかく何が問題になっていますか?古すぎませんか?
Lorinczy Zsigmond

1
@LorinczyZsigmond 何が問題になってstat(2) います言語標準の一部ではありません。
Andrew Henle

回答:


122

<filesystem>(C ++ 17で追加)これは非常に簡単です。

#include <cstdint>
#include <filesystem>

// ...

std::uintmax_t size = std::filesystem::file_size("c:\\foo\\bar.txt");

コメントで述べたように、この関数を使用してファイルから読み取るバイト数を決定する場合は、次の点に注意してください...

...ファイルがユーザーによって排他的に開かれていない限り、ファイルのサイズは、ファイルを要求してからデータを読み取ろうとするまでの間に変更できます。
–ニコルボーラス


11
少し異議あり:std::uintmax_tより大きな価値を保持できる世界はありますstd::size_tか?そうでない場合は、を使用してみませんstd::size_tか。回答の+1、ところで
Fureeish

13
@Fureeish file_size戻り値の型だからといって使用しました。私にも少し奇妙に見えます。
HolyBlackCat

39
@Fureeish std::size_tは、メモリオブジェクトの最大サイズを保持するためにのみ必要です。ファイルはかなり大きくなる可能性があります
Richard Critten

26
@Fureeishさて、32ビットWindowsでは(そして、ほとんどの最新の32ビットプラットフォームでは)size_t、32ビットであり、uintmax_t64ビットです。
HolyBlackCat

16
@HolyBlackCat:ファイルシステムがグローバルであるという事実について何か言っておくと良いでしょう。そのため、ファイルが排他的に開かれていない限り、ファイルのサイズは、要求してからデータを読み取ろうとするまでの間に変更できます。それから。
Nicol Bolas

28

C ++ 17はstd::filesystem、ファイルとディレクトリに関する多くのタスクを合理化します。ファイルサイズとその属性をすばやく取得できるだけでなく、新しいディレクトリの作成、ファイルの反復処理、パスオブジェクトの操作もできます。

新しいライブラリは、使用できる2つの関数を提供します。

std::uintmax_t std::filesystem::file_size( const std::filesystem::path& p );

std::uintmax_t std::filesystem::directory_entry::file_size() const;

最初の関数はのフリー関数std::filesystem、2番目の関数はのメソッドですdirectory_entry

各メソッドには、例外をスローしたり、エラーコードを(出力パラメーターを介して)返したりする可能性があるため、オーバーロードもあります。以下は、考えられるすべてのケースを説明する詳細コードです。

#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';
}

2
「これ」とは正確には何ですか?特に、受け入れられた回答がはるかに少ないコードを使用する場合、このすべてのコードの使用目的を説明できますか?
Nico Haase
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.