2015-02-24 53 views
0

我是C++的新手,我試圖用我的代碼做一些事情。我一直在研究如何去做,但一直沒有得到解決,並且相當不成功。在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

請參閱此處以檢查文件是否存在:http://stackoverflow.com/questions/12774207/fastest-way-to-check-if-a-file-exist-using-standard-c-c11-c – swang 2015-02-24 09:20:10

+0

你的'if(fin.is_open())'檢查文件是否存在並且可以打開 - 我建議只添加一個'else std :: cerr <<「文件名不能被打開以便讀\ n」'。如果你不在'fin.seekp(0,std :: ios_base :: end);'(for'ofstream')或'seekg'(' ifstream'),然後是'tellp' /'tellg' ...看文檔[here](http://en.cppreference.com/w/cpp/io/basic_ostream/seekp)。 – 2015-02-24 09:35:31

回答

0

看fstat,它會告訴你文件的大小(如果不存在則返回一個錯誤)。

您也可以強制複製文件的上次更新日期與源文件相同,這樣如果源文件更改但保持相同大小,您會注意到它(查看時間)。

1

對於一般的文件系統操作,有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; 

} 

編譯我的筆記本電腦(當然目錄將是具體的,無論你有頭文件和庫,但這些自制軟件如何安裝它們在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系統,並返回一個文件大小的數據包含結構,但是,微軟的系統使用GetFileSizeEx()得到一個文件的大小。因此,如果您需要便攜式解決方案,那麼您必須使用可與各種操作系統進行交互的庫,並在操作系統中呈現一致的API。

僅使用標準庫支持比較文件可以通過實現散列函數或逐字比較文件來完成。

相關問題