#include <fstream>
#include <string>
#include <cassert>
long long GetFileSizeA(const std::string& file_path)
{
return std::ifstream
{
file_path, std::ios::ate
}.tellg();
}
long long GetFileSizeB(const std::string& file_path)
{
return std::ifstream
{
file_path, std::ios::ate | std::ios::binary
}.tellg();
}
int main()
{
auto a = GetFileSizeA("~/test.log");
auto b = GetFileSizeB("~/test.log");
assert(a == b); // always true?
}
如果文件~/test.log
包含许多\r\n
个序列,那么C ++标准保证GetFileSizeA
是否与GetFileSizeB
相同?
答案 0 :(得分:1)
标准不能保证两者相等(C或C ++标准也没有说明文件是否包含\r\n
或\n
或\r
作为行尾,由操作系统和/或应用程序定义。标准C库,以及扩展的C ++库,保证如果您以文本模式读取文件,它将把任何实际的行结束转换为内部\n
形式)。它也不能保证它始终不是相同的值。
更重要的是,您可能会发现,如果您阅读文件的某些部分并询问“我在哪里”,那么如果您将其读作二进制文件或ascii文件,则答案会有所不同。如果您计划将文件映射到内存并将其作为大字符串处理,而不转换换行符,则需要将其作为二进制文件。
答案 1 :(得分:1)
C ++标准没有这样的保证。
实际上,代码
std::ifstream{file_path, std::ios::ate | std::ios::binary}.tellg();
也不保证按预期工作。对基于文件的流的tellg()
操作归结为几个中间函数(std::basic_istream::tellg
- &gt; std::basic_streambuf::pubseekoff
- &gt; std::basic_filebuf::seekoff
)并使用'好像'制定为std::fseek()
。后者isn't required to support seeking in binary streams relative to the end position:
int fseek( std::FILE* stream, long offset, int origin );
设置文件流流的文件位置指示符。
如果流以二进制模式打开,则新位置完全正确 如果原点是从文件开头测量的偏移字节
SEEK_SET
,如果来源为SEEK_CUR
,则从当前文件位置开始, 如果来源是SEEK_END
,则从文件末尾开始。 二进制流 不需要支持SEEK_END
,特别是如果有额外的话 输出空字节。