在C ++中检查文件的存在,大小和相似性

时间:2015-02-24 09:09:57

标签: 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文件是否已存在,我正在尝试做什么。

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

我该怎么做呢?

2 个答案:

答案 0 :(得分:1)

对于常规文件系统操作,有Boost Filesystem。

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

要比较文件,您可以计算哈希值并比较哈希值。对于两个文件来说,逐个字符地比较它们同样有效,但是比较哈希的两个以上文件会胜出。

为此我们有加密++。

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;

}

我的笔记本电脑上的编译(这些目录当然是特定于你拥有标题和库的地方,但这些是自制软件在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块。 (如果您只想知道文件是否存在但是您不想对文件进行操作,则明确测试存在是否有意义。)

这就是我在实践中做这些事情的方法。如果您要问的是如何在没有库的情况下完成这些操作,那么您可以使用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。

仅使用标准库支持比较文件可以通过实现散列函数或逐个字符地比较文件来完成。

答案 1 :(得分:0)

查看fstat,它会告诉你文件大小(如果不存在则返回错误)。

您还可以强制复制文件的最后更新日期与源文件相同,这样如果源文件发生更改但保持相同的大小,您会注意到它(请查看futimes这样做)。 / p>