【问题标题】:Truncate file in C [duplicate]截断文件[重复]
【发布时间】:2010-10-09 17:41:07
【问题描述】:

我正在使用 fopen fseeko64 ftello64 fclose 等对文件进行操作。

如何截断文件?我知道在 C 中没有标准的方法可以做到这一点。我想要的只是在任何 win32 平台上都可以使用的方法。我正在使用mingw gcc进行编译。

请注意:我的意思是将文件的大小截断为指定的大小,而不是使其大小为 0。并且使用诸如将部分复制到另一个文件并删除/重命名之类的技巧是不合适的。

【问题讨论】:

标签: c windows winapi


【解决方案1】:

如果您只是简单地 fopen() 一个带有 "w" 参数的文件,它将被截断。

http://www.cplusplus.com/reference/clibrary/cstdio/fopen.html

【讨论】:

    【解决方案2】:

    如果您想将文件截断为零大小,可以fopen 使用"w" 标志:

    FILE *fh = fopen("file.txt","w");
    if (fh != NULL) fclose(fh);
    

    要在标准 C 中截断为特定大小,您可以使用传输/重命名解决方案来执行此操作,例如:

    FILE *finp = fopen ("inp.txt", "rb");       // should check for NULLs
    FILE *fout = fopen ("out.txt", "wb");
    
    size_t sz = 100000;                         // 100,000 bytes
    char *buff = malloc (sz);                   // should check for NULL
    
    sz = fread (buff, 1, sz, fin);              // should check for errors
    fwrite (buff, 1, sz, fout);
    
    free (buff);
    
    fclose (fin);
    fclose (fout);
    
    rename ("out.txt", "inp.txt);               // should check for error
    

    当然,如果您可以访问 Win32 头文件和库(我相信 MinGW 会为您提供),您可以使用 SetEndOfFile(),因为它可以就地执行,而不必创建一个新文件然后重命名它。

    这意味着使用基于 Windows 句柄的文件 I/O 而不是基于 C FILE* 的文件 I/O,但是,如果您仍然将自己限制在 Windows 中,那可能没关系。另一方面,如果您想要可移植性,则需要基于标准 C 的解决方案,例如上面的传输/重命名解决方案。

    【讨论】:

    • 为什么使用指向单个字符的指针?您可以使用 fgetc() 和 fputc() 并且只使用非指针(甚至不是变量): for(int i = 0; i
    • 这将导致 100,000 倍的函数调用 :-)
    • 啊,有误读。对不起。 (不过,我不认为 100000 个 fgetc()s 和 fputc()s 真的需要那么长时间。)
    • 有趣,我打算通过编写示例程序来证明你错了,但看起来你是对的。与使用重复 fgetc/fputc 相比,使用 malloc 和重复 fread(100k)/fwrite(100K) 传输 34M 文件实际上需要更长的时间(两倍长)。所以我会明智地闭嘴:-)
    【解决方案3】:

    SetEndOfFile()

    获取具有写访问权限的文件的句柄,设置文件指针,然后调用 SetEndOfFile()。

    -亚当

    【讨论】:

    • 不幸的是,这并没有解释如何将 OP 的 FILE* 值转换为适合传递给 SetEndOfFile() 的 HANDLE
    • 除了 mentioned in the comment 已经被 @Malvineous... 我想指出您指向的是 C++ 函数,而 OP询问了 C 并相应地用 C 明确标记了问题。
    【解决方案4】:

    如前所述,您可以将 fopen() 与“w”标志一起使用,例如:

    FILE *f = fopen("file.txt", "w");
    

    另外,如果您已经打开了文件,您可以使用函数 freopen(),再次使用“w”标志:

    FILE *f = fopen("file.txt", "r");  //initial fopen() call
    ...
    f = freopen("file.txt", "w", f);   //reopens "file.txt" and truncates it
    

    http://www.cplusplus.com/reference/clibrary/cstdio/freopen.html

    编辑:在看到您编辑了您的 OP 之后,我不会重新发布 Pax 和 Adam Davis 已经发布的内容。另外,我将确认 Pax 所说的,MinGW 确实允许您访问 Win32 标头。

    【讨论】:

      【解决方案5】:

      对于基于 FILE 的文件操作,使用 _fileno() 和 _chsize_s() 来更改文件的大小。

      int changesize(FILE *fp, __int64 size)
      {
          int filedes = _fileno(fp);
          return _chsize_s(filedes, size);
      }
      

      可以通过验证提供的大小小于当前文件大小来编写截断版本,因为 _chsize_s() 将截断或扩展文件的大小 - 请参阅http://msdn.microsoft.com/en-us/library/whx354w1(VS.80).aspx

      【讨论】:

      • 假设您可以访问 Microsoft 的运行时。
      猜你喜欢
      • 1970-01-01
      • 2013-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-02
      • 2012-12-13
      • 1970-01-01
      • 2010-12-27
      相关资源
      最近更新 更多