Vin*_*ent 407 c c++ file stream
我想找到检查文件是否存在于标准C++ 11,C++或C中的最快方法.我有数千个文件,在对它们做一些事情之前我需要检查它们是否全部存在.我可以写什么而不是/* SOMETHING */
以下功能?
inline bool exist(const std::string& name)
{
/* SOMETHING */
}
Run Code Online (Sandbox Code Playgroud)
Phe*_*ide 709
好吧,我把一个测试程序放在一起,运行每个方法100,000次,一半是存在的文件,一半是没有的文件.
#include <sys/stat.h>
#include <unistd.h>
#include <string>
#include <fstream>
inline bool exists_test0 (const std::string& name) {
ifstream f(name.c_str());
return f.good();
}
inline bool exists_test1 (const std::string& name) {
if (FILE *file = fopen(name.c_str(), "r")) {
fclose(file);
return true;
} else {
return false;
}
}
inline bool exists_test2 (const std::string& name) {
return ( access( name.c_str(), F_OK ) != -1 );
}
inline bool exists_test3 (const std::string& name) {
struct stat buffer;
return (stat (name.c_str(), &buffer) == 0);
}
Run Code Online (Sandbox Code Playgroud)
运行100,000次呼叫的总时间平均超过5次,
Method exists_test0 (ifstream): **0.485s**
Method exists_test1 (FILE fopen): **0.302s**
Method exists_test2 (posix access()): **0.202s**
Method exists_test3 (posix stat()): **0.134s**
Run Code Online (Sandbox Code Playgroud)
该stat()
函数在我的系统上提供了最佳性能(Linux,编译g++
),fopen
如果由于某种原因拒绝使用POSIX函数,标准调用是最好的选择.
Vin*_*ent 124
备注:在C++ 14中,只要文件系统TS完成并采用,解决方案就是使用:
std::experimental::filesystem::exists("helloworld.txt");
Run Code Online (Sandbox Code Playgroud)
从C++ 17开始,只有:
std::filesystem::exists("helloworld.txt");
Run Code Online (Sandbox Code Playgroud)
小智 105
我使用这段代码,到目前为止它对我来说还可以.这并没有使用C++的许多奇特功能:
bool is_file_exist(const char *fileName)
{
std::ifstream infile(fileName);
return infile.good();
}
Run Code Online (Sandbox Code Playgroud)
Jim*_*ter 26
这取决于文件所在的位置.例如,如果它们都应该位于同一目录中,则可以将所有目录条目读入哈希表,然后根据哈希表检查所有名称.在某些系统上,这可能比单独检查每个文件更快.单独检查每个文件的最快方法取决于您的系统...如果您正在编写ANSI C,最快的方法是fopen
因为它是唯一的方法(文件可能存在但不可打开,但您可能真的想要打开,如果你需要"做点什么").C++,POSIX,Windows都提供了其他选项.
在我做的时候,让我指出你的问题有些问题.你说你想要最快的方式,并且你有数千个文件,但是你要求函数的代码来测试单个文件(并且该函数仅在C++中有效,而不是C).这通过对解决方案做出假设而与您的要求相矛盾......这是XY问题的一个例子.你还说"在标准的c ++ 11(或)c ++(或)c"......这些都是不同的,这也与你对速度的要求不一致......最快的解决方案是将代码定制到目标系统.问题的不一致性在于您接受了一个答案,该答案提供了依赖于系统且不是标准C或C++的解决方案.
anh*_*ppe 22
对于那些喜欢激励的人:
boost::filesystem::exists(fileName)
Run Code Online (Sandbox Code Playgroud)
Ram*_*tra 20
与PherricOxide建议的相同,但在C中
#include <sys/stat.h>
int exist(const char *name)
{
struct stat buffer;
return (stat (name, &buffer) == 0);
}
Run Code Online (Sandbox Code Playgroud)
Vik*_*ehr 19
不使用其他库,我喜欢使用以下代码片段:
#ifdef _WIN32
#include <io.h>
#define access _access_s
#else
#include <unistd.h>
#endif
bool FileExists( const std::string &Filename )
{
return access( Filename.c_str(), 0 ) == 0;
}
Run Code Online (Sandbox Code Playgroud)
这适用于Windows和POSIX兼容系统的跨平台.
小智 10
inline bool exist(const std::string& name)
{
ifstream file(name);
if(!file) // If the file was not found, then file is 0, i.e. !file=1 or true.
return false; // The file was not found.
else // If the file was found, then file is non-0.
return true; // The file was found.
}
Run Code Online (Sandbox Code Playgroud)
Windows下的另外3个选项:
inline bool exist(const std::string& name)
{
OFSTRUCT of_struct;
return OpenFile(name.c_str(), &of_struct, OF_EXIST) != INVALID_HANDLE_VALUE && of_struct.nErrCode == 0;
}
Run Code Online (Sandbox Code Playgroud)
inline bool exist(const std::string& name)
{
HANDLE hFile = CreateFile(name.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != NULL && hFile != INVALID_HANDLE)
{
CloseFile(hFile);
return true;
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
inline bool exist(const std::string& name)
{
return GetFileAttributes(name.c_str()) != INVALID_FILE_ATTRIBUTES;
}
Run Code Online (Sandbox Code Playgroud)
我需要一个可以检查文件是否存在的快速函数,而 PherricOxide 的答案几乎是我所需要的,只是它没有比较 boost::filesystem::exists 和 open 函数的性能。从基准测试结果我们可以很容易地看出:
使用 stat 函数是检查文件是否存在的最快方法。请注意,我的结果与 PherricOxide 的答案一致。
boost::filesystem::exists 函数的性能与 stat 函数非常接近,并且具有可移植性。如果可以从您的代码访问 boost 库,我会推荐这个解决方案。
使用 Linux 内核 4.17.0 和 gcc-7.3 获得的基准测试结果:
2018-05-05 00:35:35
Running ./filesystem
Run on (8 X 2661 MHz CPU s)
CPU Caches:
L1 Data 32K (x4)
L1 Instruction 32K (x4)
L2 Unified 256K (x4)
L3 Unified 8192K (x1)
--------------------------------------------------
Benchmark Time CPU Iterations
--------------------------------------------------
use_stat 815 ns 813 ns 861291
use_open 2007 ns 1919 ns 346273
use_access 1186 ns 1006 ns 683024
use_boost 831 ns 830 ns 831233
Run Code Online (Sandbox Code Playgroud)
以下是我的基准代码:
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include "boost/filesystem.hpp"
#include <benchmark/benchmark.h>
const std::string fname("filesystem.cpp");
struct stat buf;
// Use stat function
void use_stat(benchmark::State &state) {
for (auto _ : state) {
benchmark::DoNotOptimize(stat(fname.data(), &buf));
}
}
BENCHMARK(use_stat);
// Use open function
void use_open(benchmark::State &state) {
for (auto _ : state) {
int fd = open(fname.data(), O_RDONLY);
if (fd > -1) close(fd);
}
}
BENCHMARK(use_open);
// Use access function
void use_access(benchmark::State &state) {
for (auto _ : state) {
benchmark::DoNotOptimize(access(fname.data(), R_OK));
}
}
BENCHMARK(use_access);
// Use boost
void use_boost(benchmark::State &state) {
for (auto _ : state) {
boost::filesystem::path p(fname);
benchmark::DoNotOptimize(boost::filesystem::exists(p));
}
}
BENCHMARK(use_boost);
BENCHMARK_MAIN();
Run Code Online (Sandbox Code Playgroud)
如果需要区分文件和目录,请考虑以下两个都使用stat的方法,这是PherricOxide演示的最快的标准工具:
#include <sys/stat.h>
int FileExists(char *path)
{
struct stat fileStat;
if ( stat(path, &fileStat) )
{
return 0;
}
if ( !S_ISREG(fileStat.st_mode) )
{
return 0;
}
return 1;
}
int DirExists(char *path)
{
struct stat fileStat;
if ( stat(path, &fileStat) )
{
return 0;
}
if ( !S_ISDIR(fileStat.st_mode) )
{
return 0;
}
return 1;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
563997 次 |
最近记录: |