C ++ 17을 사용하여 파일 크기를 바이트 단위로 가져 오는 방법


97

특정 운영 체제에 대해 알아야 할 함정이 있습니까?

이 질문의 중복 ( 1 , 2 , 3 , 4 , 5 )이 많이 있지만 수십 년 전에 답변되었습니다. 오늘날 이러한 많은 질문에서 매우 높은 투표를받은 답변은 잘못된 것입니다.

.sx의 다른 (이전 QA) 메서드

  • stat.h (래퍼 sprintstatf ), syscall 사용

  • tellg () 는 정의에 따라 위치를 반환 하지만 반드시 bytes는 아닙니다 . 반환 유형이 아닙니다 int.



5
@LF : 글쎄요, 첫 번째 질문은 두 번째 질문의 중복으로 닫혔습니다. 첫 번째 질문에서 받아 들여진 대답 이 잘못된 이유를 설명합니다 . 세 번째는 유사한 tellg문제 에 대해 묻는 것입니다. 귀찮게 할 가치가있는 유일한 것은 네 번째 ofstream질문이며 질문과 답변 모두 에 대해 너무 많이 이야기하기 때문에 그다지 좋지 않습니다 . 이것은 다른 것보다 의도를 표현하는 데 훨씬 낫습니다 (이상하게 닫혀있는 첫 번째를 제외하고).
Nicol Bolas

6
질문과 질문 제목에 관련없는 정보를 추가하지 마십시오. 연도는 관련이 없습니다. 기술이 관련이 있습니다.
elixenide

2
stat(2)어쨌든 뭐가 잘못 됐나요? 너무 늙었나요?
Lorinczy Zsigmond

1
@LorinczyZsigmond 무엇이 잘못stat(2) 되었는가 언어 표준의 일부가 아닙니다.
Andrew Henle

답변:


123

<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, btw
Fureeish 19

13
@Fureeish 나는 유형이 file_size반환 되기 때문에 사용했습니다 . 나에게도 약간 이상해 보인다.
HolyBlackCat 19

39
@Fureeish std::size_t는 메모리 개체의 최대 크기를 유지하는 데만 필요합니다. 파일은 상당히 클 수 있습니다
리처드 Critten

26
@Fureeish 음, 32 비트 Windows (그리고 대부분의 최신 32 비트 플랫폼에서 가정) size_t에서는 32 비트이고 uintmax_t64 비트입니다.
HolyBlackCat 19

16
@HolyBlackCat : 파일 시스템이 전역 적이라는 사실에 대해 말하면 좋을 것입니다. 따라서 파일을 독점적으로 열지 않는 한 파일 크기는 요청한 시간과 데이터를 읽으려고 할 때 사이에 변경 될 수 있습니다. 이것으로부터.
Nicol Bolas

28

C ++ 17은 std::filesystem파일 및 디렉토리에 대한 많은 작업을 간소화합니다. 파일 크기와 속성을 빠르게 얻을 수있을뿐만 아니라 새 디렉토리를 만들고 파일을 반복하며 경로 개체로 작업 할 수도 있습니다.

새 라이브러리는 사용할 수있는 두 가지 기능을 제공합니다.

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

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

첫 번째 함수는의 무료 함수이고 두 번째 함수는 std::filesystem의 메서드입니다 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
"this"가 정확히 무엇입니까? 이 모든 코드가 어떤 용도로 사용되는지 설명해 주시겠습니까? 특히 수락 된 답변이 훨씬 적은 코드를 사용하는 경우에 그렇습니다.
Nico Haase
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.