【问题标题】:Use std::ifstream::read to count the number of character使用 std::ifstream::read 计算字符数
【发布时间】:2016-02-06 16:34:49
【问题描述】:

显然是这段代码:

std::ifstream filev(path, std::ios::binary|std::ios::in);
unsigned long int nData = 0;
filev.read((char*)&nData, sizeof(nData) );

正如@IgorTandetnik 建议的那样,由于文件头,特别是在Windows 上,执行结束时nData 将包含文件的大小。

现在我想知道为什么同一处理器上的这段代码在不同的 S.O 上给出不同的结果。

谁能给我解释一下为什么 MSVC 让这段代码工作?

【问题讨论】:

  • can be used ... to count the number of bytes 不,不是。它所做的只是从文件中读取前 4 或 8 个字节,并将它们解释为整数的表示。您正在使用的特定文件格式可能恰好将文件大小存储在前几个字节中(或者某个特定文件的前几个字节恰好与其文件大小匹配纯属巧合),但对于任意文件通常并非如此.
  • unsigned long int32 bit large on Windows and 64 bit on Linux;这就是为什么相同的代码在不同平台上从相同文件中检索不同值的原因(换句话说,您的代码不可移植)。不过,鉴于您显示的数据,我看不出您如何最终获得 0x3e4fc7a8 的值;我怀疑你在这方面是错误的。无论如何,当您需要以可移植方式具有特定位大小的整数时,请使用uint32_t et al
  • 感谢您的帮助,您是对的,我已经根据您的建议编辑了问题,如果您从您的 cmets 中做出回答,我会将其标记为解决方案。

标签: visual-c++ gcc ifstream


【解决方案1】:

这与文件大小完全没有关系(您的文件可能碰巧在其前 4 个字节中存储了自己的大小,但对于任意文件来说并非如此,而且无论如何都不是重点)。

您的代码表现出实现定义的行为;换句话说,它是不可移植的。特别是,unsigned long int32 bit large on Windows and 64 bit on Linux,所以你有时会读取文件的前 4 个字节,有时会读取前 8 个字节;自然,当这些字节被解释为整数的二进制表示时,这会导致不同的值。

当您需要特定位大小的整数时,请使用unit32_t et al

这仍然留下了整数的二进制表示本身是实现定义的事实,即使两个实现使用相同大小的整数。例如,如果您曾经在大端平台上运行此代码(幸运的是,这些天有些罕见)或不使用二进制补码表示的平台(这些几乎不存在),您会感到惊讶)。

【讨论】:

    猜你喜欢
    • 2012-10-12
    • 1970-01-01
    • 2011-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多