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



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

这是我的代码:

编辑:

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

main:

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

tellg不报告文件的大小,也不报告偏移量从开始以字节为单位。它报告一个令牌值,该值可以后来被用来寻找同一个地方,什么都没有。(甚至不能保证您可以将类型转换为积分型。)

至少根据语言规范:在实践中,在Unix系统上,返回的值将是以字节为单位的偏移量从文件的开头,在Windows下对于在中打开的文件,从文件开始的偏移量二进制模式。对于Windows(以及大多数非Unix系统),以文本形式模式下tellg返回和必须读取才能到达的字节数这个位置。在Windows下,你真正能指望的就是该值将不小于您拥有的字节数阅读(在大多数真实情况下,不会太大,尽管它可以高达两倍以上)。

如果知道你能读取多少字节很重要,唯一可靠的方法是阅读。你应该可以用这样的东西来做到这一点

#include <limits>
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];

不应该编译:您已经将CCD_ 3声明为CCD_,所以*buffer具有类型char并且不是指针。给定什么您似乎正在执行,您可能想要将buffer声明为CCD_ 8。但更好的解决方案是宣布作为CCD_ 9或CCD_。(那样,你不必返回大小,也不会泄露内存如果出现异常。)

其次,末尾的循环条件是错误的。如果你真的想要一次读取一个字符,

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(但存在某种更精确的错误处理可能更好)。

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

  • std::files系统::file_size-cppreference.com
  • std::filesystem::directory_entry::file_size-cppreference.com

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

这些函数还只需要目录读取权限,而不需要文件读取权限(如tellg()所做的)

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];
...
fseek(fptr, 0L, SEEK_END);
filesz = ftell(fptr);

如果文件通过fopen 打开,将执行该文件

使用ifstream、

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

会做类似的

相关内容

  • 没有找到相关文章

最新更新