tellg()函数给出错误的文件大小?

时间:2014-04-10 10:08:50

标签: c++ file ifstream

我做了一个示例项目,将文件读入缓冲区。 当我使用tellg()函数时,它给我一个比值大的值 读取函数实际上是从文件中读取的。我认为有一个错误。

这是我的代码:

修改

void read_file (const char* name, int *size , char*& buffer)
{
  ifstream file;

  file.open(name,ios::in|ios::binary);
  *size = 0;
  if (file.is_open())
  {
    // get length of file
    file.seekg(0,std::ios_base::end);
    int length = *size = file.tellg();
    file.seekg(0,std::ios_base::beg);

    // allocate buffer in size of file
    buffer = new char[length];

    // read
    file.read(buffer,length);
    cout << file.gcount() << endl;
   }
   file.close();
}

主:

void main()
{
  int size = 0;
  char* buffer = NULL;
  read_file("File.txt",&size,buffer);

  for (int i = 0; i < size; i++)
    cout << buffer[i];
  cout << endl; 
}

4 个答案:

答案 0 :(得分:47)

tellg不报告文件的大小,也不报告偏移量 从字节开始。它报告一个可以的令牌值 后来被用来寻找同一个地方,仅此而已。 (甚至不能保证你可以将类型转换为 积分型。)

至少根据语言规范:在实践中, 在Unix系统上,返回的值将是以字节为单位的偏移量 从文件的开头,在Windows下,它将是 文件开头的偏移量,用于打开的文件 二进制模式。对于Windows(和大多数非Unix系统),在文本中 什么模式,没有直接和即时的映射 tellg返回以及必须读取的字节数 那个位置。在Windows下,您真正​​依赖的是 该值将不小于您拥有的字节数 阅读(在大多数情况下,不会太大, 虽然它可以多达两倍)。

如果确切知道您可以读取多少字节很重要, 可靠这样做的唯一方法是阅读。你应该 能够做到这样的事情:

file.ignore( std::numeric_limits<std::streamsize>::max() );
std::streamsize length = file.gcount();
file.clear();   //  Since ignore will have set eof.
file.seekg( 0, std::ios_base::beg );

最后,关于你的代码的其他两个评论:

首先,行:

*buffer = new char[length];

不应该编译:您已将buffer声明为char*, 所以*buffer的类型为char,而不是指针。鉴于什么 你似乎在做,你可能想要声明buffer 一个char**。但更好的解决方案是宣布它 作为std::vector<char>&std::string&。 (那样,你 不必返回大小,也不会泄漏内存 如果有例外。)

其次,最后的循环条件是错误的。如果你真的 想要一次阅读一个角色,

while ( file.get( buffer[i] ) ) {
    ++ i;
}

应该做的伎俩。一个更好的解决方案可能是 读取数据块:

while ( file.read( buffer + i, N ) || file.gcount() != 0 ) {
    i += file.gcount();
}

甚至:

file.read( buffer, size );
size = file.gcount();
编辑:我刚注意到第三个错误:如果你打不开 文件,你不告诉来电者。至少,你应该 将size设置为0(但某种更精确的错误 处理可能更好)。

答案 1 :(得分:3)

在C ++ 17中,有std::filesystem file_size个方法和函数,因此可以简化整个任务。

有了这些功能/方法,就有机会不打开文件而是读取缓存的数据(尤其是使用std::filesystem::directory_entry::file_size方法)

这些功能也只需要目录读取权限,而不需要文件读取权限(如tellg()一样)

答案 2 :(得分:0)

void read_file (int *size, char* name,char* buffer)
*buffer = new char[length];

这些行看起来像一个bug:你创建一个char数组并保存到buffer [0] char。然后你读取一个缓冲的文件,它仍未被初始化。

您需要通过指针传递buffer

void read_file (int *size, char* name,char** buffer)
*buffer = new char[length];

或者通过引用,这是c ++方式,并且不易出错:

void read_file (int *size, char* name,char*& buffer)
buffer = new char[length];
...

答案 3 :(得分:-1)

fseek(fptr, 0L, SEEK_END);
filesz = ftell(fptr);
如果通过fopen

打开文件,

将执行该文件

使用ifstream,

in.seekg(0,ifstream::end);
dilesz = in.tellg();

会做类似的