【问题标题】:Is there a way to get size of a file on Windows using C?有没有办法使用 C 在 Windows 上获取文件的大小?
【发布时间】:2020-07-26 14:13:42
【问题描述】:

我目前正在尝试使用 C 的 fread 函数在 Windows 上读取文件的全部内容。此函数需要将正在读入的缓冲区的大小作为参数传递。因为我想读取整个文件,所以我需要以字节为单位传递文件的大小。

我尝试通过使用 Win32 API 来获取 Windows 上文件的大小,更具体地说,使用 GetFileSizeEx。下面的 sn-p 来自an existing Stack Overflow answer

__int64 GetFileSize(const char* name)
{
    HANDLE hFile = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if(hFile == INVALID_HANDLE_VALUE)
        return -1; // error condition, could call GetLastError to find out more

    LARGE_INTEGER size;
    if(!GetFileSizeEx(hFile, &size))
    {
        CloseHandle(hFile);
        return -1; // error condition, could call GetLastError to find out more
    }

    CloseHandle(hFile);
    return size.QuadPart;
}

此函数返回的大小比实际文件大小。执行以下代码块后

FILE* file = fopen(path, "r");
long size = (long)GetFileSize(path);
char* buffer = new char[size + 1];
fread(buffer, 1, size, file);
buffer[size] = '\0';

缓冲区的末尾包含垃圾字节。我已经手动检查过,返回的大小肯定比实际大小(以字节为单位)大。

我已经尝试了上面链接的同一个 Stack Overflow 答案中描述的其他方法,但它们都会在缓冲区末尾产生垃圾字节。

【问题讨论】:

  • generic C 你寻找到最后并获得文件位置是吗?
  • @old_timer 我也试过了,但这似乎不是标准的,而且它还返回比实际尺寸更大的尺寸。即使使用“r”和“rb”阅读模式。
  • GetFileSize 以及寻找到最后都应该为您提供准确的文件大小。您是如何确定“实际文件大小”的?也许那个方法是错误的。
  • 你说“最后包含垃圾字节”。是从缓冲区读取垃圾还是垃圾?你检查了吗?此外new char[size] 是 C++,而不是 C。
  • 文件大小的基准是多少?

标签: c file


【解决方案1】:

FILE* file = fopen(path, "r"); 应该是FILE* file = fopen(path, "rb"); 如果您想要精确的大小,请以二进制模式打开文件。

在 Windows 上,以文本模式读取文件会导致 "\r\n" 序列转换为 "\n",从而导致读取的字节数少于预期。

【讨论】:

  • 由于某种原因,使用二进制模式以前不起作用,但现在可以了。我希望这是我的问题,而不是功能。谢谢!
【解决方案2】:

你应该以二进制模式打开文件,你应该使用 fseek 和 ftell 来获取文件大小,这是可移植的方式。这样你就摆脱了 windows 文本模式的转换。

FILE* file = fopen(path, "rb");
fseek(file,0,SEEK_END) ; //move to 0 bytes to the end
long size=ftell(file); //get the size (pos at end)
rewind(file); //same as fseek(file,0,SEEK_SET), move the position to the begining

char* buffer = new char[size + 1];
long bytes_read=fread(buffer, 1, size, file);
buffer[bytes_read]=0;
if (bytes_read!=size)
{
// check errors (feof)

}

【讨论】:

    【解决方案3】:

    在仅使用 C 标准函数的任何系统上读取文件大小的标准方法是使用 fseek()ftell() 函数:

    #include <stdio.h>
    long get_file_len(char *filename)
    {
        long int size=0;
        FILE *fp= fopen ( filename , "rb" );
        if (!fp)
            return 0;
        fseek (fp,0,SEEK_END);    //move file pointer to end of file
        size= ftell (fp);
        fclose(fp);
        return size;
    }
    

    作为变体你也可以使用lseek():

    #include <stdio.h>
    long get_file_len(char *filename)
    {
        long int size=0;
        FILE *fp= fopen ( filename , "rb" );
        if (!fp)
            return 0;
        size = lseek (fp,0,SEEK_END);    //move file pointer to end of file
        fclose(fp);
        return size;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-27
      • 2011-11-26
      • 2017-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多