c++ - 在 C++ 中检查文件是否存在、大小和相似性

标签 c++ file streaming ifstream

我是 C++ 的新手,我想用我的代码做一些事情。我一直在研究如何做它们,但一直无法理解它,而且相当不成功。

bool Copy(char filenamein[], char filenameout[]);

int main(int argc, char **argv)
{
    if (argc !=3) {
        cerr << "Usage: " << argv[0] << " <input filename> <output filename>" << endl;
        int keypress; cin >> keypress;
        return -1;
    }

    if (Copy(argv[1], argv[2]))
        cout << "Copy completed" << endl;
    else
        cout << "Copy failed!" << endl;

    system("pause");

    return 0;
}

bool Copy(char filenamein[], char filenameout[])
{
    ifstream fin(filenamein);
    if(fin.is_open())
    {
        ofstream fout(filenameout);

        char c;
        while(fin.get(c))
        {
            fout.put(c);
        }

        fout.close();
        fin.close();

        return true;
    }

    return false;
}

这段代码已经创建了 2 个文本文件,input.txt 和 output.txt。这两个文件还包含相同的项目/字符。

如果在尝试复制之前检查 input.txt 文件是否已经存在,我正在尝试做什么。

我还想检查这两个文件以确保它们相同,并检查文件大小是否相等。

我该怎么做呢?

最佳答案

对于一般的文件系统操作,有 Boost Filesystem。

http://www.boost.org/doc/libs/1_57_0/libs/filesystem/doc/index.htm

要比较文件,您可以计算哈希值并比较哈希值。对于两个文件,逐个字符比较它们同样有效,但对于两个以上的文件,比较哈希值更胜一筹。

为此,有 Crypto++。

http://www.cryptopp.com/

使用两个库解决问题中的3个问题的示例。

// C++ standard library
#include <iostream>

// Boost
#include <boost/filesystem.hpp>

// Crypto++
#include <cryptopp/sha.h>
#include <cryptopp/hex.h>
#include <cryptopp/files.h>

using std::string;

const string file_hash(const boost::filesystem::path &file);

int main( int argc, char** argv) {
    if (argc != 3)
    {
        std::cout << "Usage: " << argv[0]  << "filepath1 filepath2\n";
        return 1;
    }

    const string filename1(argv[1]);
    const string filename2(argv[2]);
    std::cout << "filename 1: " << filename1 << std::endl;
    std::cout << "filename 2: " << filename2 << std::endl;

    // file existence
    const bool file_exists1 = boost::filesystem::exists(filename1);
    const bool file_exists2 = boost::filesystem::exists(filename2);
    std::cout << "file 1 exists: " << std::boolalpha << file_exists1 << std::endl;
    std::cout << "file 2 exists: " << std::boolalpha << file_exists2 << std::endl;

    if (!file_exists1 || !file_exists2)
        return EXIT_SUCCESS;

    // file size
    const boost::filesystem::path file_path1(filename1);
    const boost::filesystem::path file_path2(filename2);

    const uintmax_t file_size1 = boost::filesystem::file_size(file_path1);
    const uintmax_t file_size2 = boost::filesystem::file_size(file_path2);
    std::cout << "file 1 size: " << std::boolalpha << file_size1 << std::endl;
    std::cout << "file 2 size: " << std::boolalpha << file_size2 << std::endl;

    // comparing files
    const string hash1 = file_hash(file_path1);
    const string hash2 = file_hash(file_path2);
    std::cout << "hash1: " << hash1 << std::endl;
    std::cout << "hash2: " << hash2 << std::endl;

    const bool same_file = hash1 == hash2;
    std::cout << "same file: " << same_file << std::endl;
}

const string file_hash(const boost::filesystem::path& file)
{
    string result;
    CryptoPP::SHA1 hash;
    CryptoPP::FileSource(file.string().c_str(),true,
            new CryptoPP::HashFilter(hash, new CryptoPP::HexEncoder(
                    new CryptoPP::StringSink(result), true)));
    return result;

}

在我的笔记本电脑上编译(目录当然会特定于您拥有 header 和库的位置,但这些是自制软件在 OS X 上安装它们的方式):

clang++ -I/usr/local/include -L/usr/local/lib -lcryptopp -lboost_system -lboost_filesystem demo.cpp -o demo

示例用法:

$ ./demo demo.cpp demo.cpp
filename 1: demo.cpp
filename 2: demo.cpp
file 1 exists: true
file 2 exists: true
file 1 size: 2084
file 2 size: 2084
hash1: 57E2E81D359C01DA02CB31621C9565DF0BCA056E
hash2: 57E2E81D359C01DA02CB31621C9565DF0BCA056E
same file: true
$ ./demo demo.cpp Makefile
filename 1: demo.cpp
filename 2: Makefile
file 1 exists: true
file 2 exists: true
file 1 size: 2084
file 2 size: 115
hash1: 57E2E81D359C01DA02CB31621C9565DF0BCA056E
hash2: 02676BFDF25FEA9E3A4D099B16032F23C469E70C
same file: false

如果您尝试执行诸如获取不存在的文件的大小之类的操作,Boost Filesystem 将抛出异常。您应该准备好捕获这些异常,这样您就不需要显式测试文件是否存在,因为无论如何您都应该有一个 catch block 。 (如果您只想知道文件是否存在,但又不想对该文件做任何事情,那么显式地测试文件是否存在是有意义的。)

这就是我在实践中做这些事情的方式。如果您要问的是没有库如何完成这些事情,那么您可以通过使用 C 或 C++ 标准库尝试打开文件并检查是否成功来检查文件是否存在。为了检查文件大小,您可以打开一个文件,您可以查找到末尾并将位置与文件的开头进行比较。

但是,一般来说,最好依靠操作系统支持来与文件系统交互。

https://www.securecoding.cert.org/confluence/display/seccode/FIO19-C.+Do+not+use+fseek%28%29+and+ftell%28%29+to+compute+the+size+of+a+regular+file

例如,

fstat() 特定于 Unix 和类 Unix 系统,并返回包含文件大小数据的结构,但在 Microsoft 系统上,您使用 GetFileSizeEx() 来获取文件大小。正因为如此,如果您想要一个可移植的解决方案,那么您必须使用与各种操作系统交互的库,并提供跨操作系统的一致 API。

可以通过实现哈希函数或逐字符比较文件来仅使用标准库支持来比较文件。

关于c++ - 在 C++ 中检查文件是否存在、大小和相似性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28691789/

相关文章:

java - 如何检索内部存储器中的每个文件?

java - 查找一个字符串并显示行号和行本身?

iphone - 如何从AVPlayer获取音频流状态的通知?

audio - 平滑流和AAC低复杂度音频编解码器。数据格式?

c++ - 如何使用 C 编程从 dbus 传递/返回结构?

C++运算符的多重定义>>

c - 文件 I/O 的故障修复策略

wcf - WCF webservice 流式响应的最佳实践

c++ - 使用 opencv 编译代码 -/usr/bin/ld : cannot find -lippicv

c++ - VTKActor 在渲染后不可见但在相机->resetview() 上可见