не удалось определить размер, если fclose не выполняется дважды

#c #fclose

#c #fclose

Вопрос:

Я создал файловый класс, который является своего рода оболочкой типа ФАЙЛА, и добавил некоторые методы.

Это код моего класса file :

           #include <Fs/File.h>



File::File(Pathamp; p):
    m_path(p),
    m_openned(false)
{
}

int File::open(const stringamp; 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, amp;file_status) < 0)
    {
        return -1;
    }

    return file_status.st_size;
}

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

    if (stat(m_path, amp;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(FileModeamp; mode)
{
    return chmod(m_path, mode);
}

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

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

int File::copyTo(Fileamp; 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);
}
 

Я провел несколько тестов, и у меня возникла проблема

             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());
 

Я не мог понять, зачем нужен этот f2.close, потому что я выполнил закрытие в методе CopyTo.
Кто-нибудь может мне помочь?
Заранее благодарю вас.
Ben

Комментарии:

1. Всегда есть Boost. Файловая система, предлагаемая для C TR2.

2. В copyTo случае this->close() сбоя вы никогда не вызываете to.close() . Однако, вероятно, это не причина вашей проблемы.

3. Вы уверены, что всегда достигаете close in copyTo ? Кажется, что там много return операторов.

Ответ №1:

В File::copyTo :

     if (ch == -1)
        return 0;
 

вы выходите из функции без надлежащего закрытия файлов. Когда целевой файл не закрыт, его содержимое, вероятно, не отправляется в ОС, которая позже сообщает о поддельном размере файла.

Ответ №2:

fclose сбрасывает поток. Я предполагаю, что без закрытия файла поток не был полностью записан, поэтому размеры разные. Подумайте о добавлении fflush(to); в конце вашего copyTo метода, чтобы убедиться, что все было написано.

Ответ №3:

У вас есть несколько выходов из функции CopyTo, которая не гарантирует, что вы действительно закроете файл. Мне кажется, что вы, возможно, рано выходите из функции CopyTo и что предполагаемое закрытие не выполняется

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

    if (ch == -1)
        return 0;

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

когда вы нажмете на конец файла, вы получите значение EOF, которое в моей ОС (Windows) равно -1, что приведет к тому, что вы вернете здесь 0 и пропустите вызов закрытия.