【问题标题】:Why would a stat() call return am incorrect value of zero(0) for file size?为什么 stat() 调用会为文件大小返回不正确的零 (0) 值?
【发布时间】:2011-11-28 17:37:57
【问题描述】:

我正在运行一个 windows c++ 多线程应用程序,其中服务器类的一个实例/线程正在附加到文件中。其他线程运行仅加载文件的客户端实例 每个客户的启动。 当我到达加载文件结束后的 2k 字节内时,我检查文件是否已更改 大小,所以我知道要更新要读取的总字节数。有时文件大小 我回来被错误地确定为零(0)。为此,我正在使用下面的 stat 调用。当返回零时,作为健全性检查,我然后调用 getFileSizeWithTellg() 来查看它返回的内容并返回预期的非零值。等于或大于初始值的值。 我意识到强制转换为 unsigned int 可能有问题,但文件永远不会 大于 5 mgBytes。

当 ..Tellg 调用没有返回零值时,什么可能导致 stat() 调用返回零值? 感谢您对此的任何见解。

/

/ snippets from methods in different classes
//
// from client class
ifstream fileSeqIn
fileSeqIn.open(fName.c_str(), ios::in | ios::binary |ios::ate); 
// to get initial size
size = fileSeqIn.tellg();
fileSeqIn.seekg(0, ios::beg);


// later to determine if the file has grown
struct stat filestatus;
unsigned int size;
if (stat(fName, &filestatus ) == 0) {
     size = (unsigned int)filestatus.st_size;   
}

//
unsigned int getFileSizeWithTellg(char *fname)
{
    // get length of file
    is.open (fname, ios::binary );
    is.seekg (0, ios::end); 
    length = is.tellg();
    is.close();
    return(length);
}


//-----------------------------------------------------------------------------
// from server class
ofstream fileSeqOut;
fileSeqOut.open(fName.c_str(), ios::app | ios::out |ios::ate |ios::binary);

【问题讨论】:

    标签: c++ windows visual-c++


    【解决方案1】:

    一个显着的区别:stat 返回系统对文件大小的看法; tellg 返回一个取决于流内部状态的值。文件基础流被缓冲,在您刷新或关闭文件之前,数据可能不会传递到系统。如果您在调用 stat 之前先刷新流,是否会得到同样的区别?

    【讨论】:

    • 更具体一点:stat() 调用返回 FindFirstFileEx 返回的文件大小 - 在文件关闭之前,此信息不可靠。
    • 这是相当随机的。但是写完之后我并没有脸红。但现在我是。另外,在加载开始时我使用tellg。当我接近尾声时,我使用 stat 因为它不会更改文件指针位置,而我需要移动到文件的 ed 然后调用 tellg 并重新定位回我所在的位置,这只是多一点代码.但这可能是要走的路。在写入线程上的每次写入后与刷新结合使用,应该可以正常工作。对吗?
    • 如果您需要有关文件状态的准确信息并且您拥有文件句柄,请调用使用句柄的 API,而不是使用文件名的 API。通常,使用文件名的 API 不如使用句柄的 API 准确(句柄总是反映文件状态的最新文件系统测量值)。
    • @LarryOsterman 应该没有区别,只要名称指的是同一个文件。
    • @AlKurlansky 如果tellg 有效,那么您不需要冲洗; tellg 是否给你有用的东西取决于实现(但如果你使用stat,你已经依赖于实现了)。 stat 当然,只会报告您实际输出系统的字节,因此您需要刷新。一个更好的系统可能是安装一个过滤流缓冲区,它计算发送给它的字节数。
    【解决方案2】:

    如果 Larry Osterman 说的是真的,使用 GetFileInformationByHandle 可能会解决问题。

    【讨论】:

    • 您或其他任何人都可以通过检查您的 MSVS 安装目录中的 crt-src\stat.c 来验证 Osterman 先生确实在说真话。
    • 使用 GetFileInformationByHandle 的一个次要警告 - 我相信它需要打开文件以进行 FILE_QUERY_INFORMATION 访问 - 如果您为 GENERIC_READ 打开文件,这将毫无问题地工作,但如果您只打开 GENERIC_WRITE 文件,则不会。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-16
    • 1970-01-01
    • 1970-01-01
    • 2014-05-22
    相关资源
    最近更新 更多