如果 fclose 未执行两次,则无法确定大小

发布于 2024-12-11 15:34:18 字数 3449 浏览 2 评论 0原文

我创建了一个 File 类,它是 FILE 类型的一种包装器,并添加了一些方法。

这是我的文件类的代码:

          #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);
}

我做了一些测试,但遇到了一个问题

            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 方法中做了关闭。 有人可以帮助我吗? 先感谢您。 本

I'm made a File class that is a sort of wrapper of the FILE type and added some methods.

This is the code of my file class :

          #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);
}

I made some tests and I have a kind of problem

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

I couldn't figure why this f2.close is needed because I did a close in the copyTo method.
Can someone help me ?
Thank you in advance.
Ben

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

无所的.畏惧 2024-12-18 15:34:18

在 File::copyTo 中:

    if (ch == -1)
        return 0;

您在没有正确关闭文件的情况下跳出了函数。当目标文件未关闭时,它的内容可能不会发送到操作系统,操作系统稍后会报告虚假文件大小。

In File::copyTo:

    if (ch == -1)
        return 0;

you are jumping out of the function without properly closing the files. When the target file is not closed, it's contents is probably not sent to the OS, which later reports bogus filesize.

萌︼了一个春 2024-12-18 15:34:18

fclose 刷新流。我的猜测是,在不关闭文件的情况下,流尚未完全写入,因此大小不同。考虑在 copyTo 方法末尾添加 fflush(to); 以确保所有内容均已写入。

fclose flushes the stream. My guess is, is that without closing the file, the stream has not been fully written, so the sizes are different. Consider adding fflush(to); at the end of your copyTo method to ensure everything has been written.

苦妄 2024-12-18 15:34:18

您从 copyTo 函数中多次退出,这并不能确保您实际关闭文件。在我看来,您可能会提前退出 copyTo 函数,并且

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

    if (ch == -1)
        return 0;

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

当您到达文件末尾时,预期的关闭不会执行,您将得到 EOF,在我的操作系统(windows)中它是 -1,这会导致你在这里返回 0,并跳过千钧一发。

You have multiple exits from the copyTo function which doesn't ensure that you actually close the file. It looks to me that you may be exiting early from the copyTo function and that the intended close isn't executing

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

    if (ch == -1)
        return 0;

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

when you hit the end of the file you will get EOF which in my os (windows) it is -1, which would cause you to return 0 here, and skip the close call.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文