2011-10-23 1 views
0

FILEタイプのラッパーであるFileクラスを作成し、いくつかのメソッドを追加しました。fcloseが2回実行されていないとサイズを特定できませんでした

これは私のファイルクラスのコードです:

  #include <Fs/File.h> 



File::File(Path& p): 
    m_path(p), 
    m_openned(false) 
{ 
} 

int File::open(const string& mode) 
{ 
    m_f = new FILE; 
    fopen(m_path, mode.c_str()); 
    if (m_f == NULL) 
    { 
     m_openned = false; 
     return -1; 
    } 
    m_openned = true; 
    return 0; 
} 

bool File::exists() 
{ 
    FILE* file; 

    if (file = fopen(m_path, "r")) 
    { 
     fclose(file); 
     return true; 
    } 

    fclose(file); 
    return false; 
} 

int File::flush(){ 
    return fflush(m_f); 
} 

int File::remove() 
{ 
    return ::remove(m_path); 
} 

int File::close() 
{ 
    if (isOpenned()) 
    { 
     m_openned = false; 
     return fclose(m_f); 
    } 

    return 0; 
} 

long File::getSize() 
{ 
    struct stat file_status; 
    if(!this->exists()) 
     return -1; 
    if (stat(m_path, &file_status) < 0) 
    { 
     return -1; 
    } 

    return file_status.st_size; 
} 

FileMode File::getMode() 
{ 
    struct stat file_status; 

    if (stat(m_path, &file_status) < 0) 
    { 
     return FileMode(-1); 
    } 

    return FileMode(file_status.st_mode); 
} 



Path File::getPath() 
{ 
    return m_path; 
} 


bool File::isOpenned() 
{ 
    return m_openned; 
} 


int File::setMode(FileMode& mode) 
{ 
    return chmod(m_path, mode); 
} 

int File::renameTo(File& f) 
{ 
    if (f.exists() || !this->exists()) 
     return -1; 

    return rename(m_path , f.getPath()); 
} 

int File::copyTo(File& to) 
{ 
    char ch; 
    this->close(); 
    this->open(FileTypes::READ); 
    to.close(); 
    to.open(FileTypes::WRITE); 

    while (!this->eof()) 
    { 
     ch = this->readc(); 

     if (ch == -1) 
      return 0; 

     if (!to.eof()) 
      to.writec(ch); 
    } 

    if (this->close() < 0) 
    { 
     return -1; 
    } 

    if (to.close() < 0) 
    { 
     return -1; 
    } 

    return 0; 
} 

int File::readc() 
{ 
    if (!isOpenned()) 
     return FileTypes::ENDOFFILE; 

    char c = fgetc(m_f); 

    if (ferror(m_f)) 
    { 
     return FileTypes::ENDOFFILE; 
    } 

    return c; 
} 

int File::writec(char c) 
{ 
    if (!isOpenned()) 
     return -1; 

    fputc(c, m_f); 

    if (ferror(m_f)) 
    { 
     return FileTypes::ENDOFFILE; 
    } 

    return 0; 
} 

bool File::eof() 
{ 
    if (!isOpenned()) 
     return true; 

    return feof(m_f); 
} 

このf2.closeが必要な理由を私は理解できなかった私はいくつかのテストをしたと私は問題

  Path p1("test.txt"); 
    Path p2("temp.txt"); 

    File f1(p1); 
    File f2(p2); 

    assert(f1.open(FileTypes::READ) == 0); 
    assert(f1.exists() == true); 
    assert(f1.close() == 0); 

    cout<<"Mode of f1 "<<f1.getMode().getStringMode()<<endl; 
    cout<<"Path of f1 "<<f1.getPath().getAbsolutePath()<<endl; 
    cout<<"Size of f1 "<<f1.getSize()<<endl; 

    assert(f2.exists() == false); 
    assert(f1.copyTo(f2) == 0); 
      //##################################### 
      // If I comment f2.close() the        
      // assert(f1.getSize() == f2.getSize()) test fails and     
      // f2.getSize() == 0 
      ########################################## 
    f2.close(); 

    assert(f2.exists() == true); 
    assert(f1.getSize() == f2.getSize()); 

のようなものを持っています私がcopyToメソッドでクローズしたからです。 誰かが私を助けることができますか? ありがとうございます。 ベン

+0

Boost.Filesystemは、常にC++ TR2用に提案されています。 –

+0

'copyTo'では、' this-> close() 'が失敗した場合、あなたは' to.close() 'を決して呼び出しません。しかし、それはおそらくあなたの問題の原因ではありません。 –

+0

あなたはいつも 'copyTo'の' close'に到達していますか?そこには多くの 'return'ステートメントがあるようです。 – Xyand

答えて

0

if (ch == -1) 
     return 0; 

あなたが適切にファイルを閉じることなく機能の飛び出しています。ターゲットファイルがクローズされていない場合、その内容はOSに送信されない可能性があります。後でOSは偽のファイルサイズを報告します。

+0

ありがとうございます!それはうまくいった。 –

0

fcloseはストリームをフラッシュします。私の推測では、ファイルを閉じることなく、ストリームが完全に書き込まれていないので、サイズが異なります。 copyToメソッドの最後にfflush(to);を追加して、すべてが書き込まれていることを確認してください。 File::copyTo

+0

私はそれを試みましたが、私はまだ同じ問題を抱えています... –

0

あなたは実際にファイルを閉じることを保証しないcopyTo関数から複数の出口があります。それはそれをあなたがのcopyTo関数からの早期退出することができるとあなたは私のOSで(窓)EOFを取得するファイルの最後にヒットしたときにすることを意図したクローズは

while (!this->eof()) 
{ 
    ch = this->readc(); 

    if (ch == -1) 
     return 0; 

    if (!to.eof()) 
     to.writec(ch); 
} 

を実行していないように私には見えます-1の場合、ここで0が返され、クローズコールはスキップされます。