在C语言中以“r+”模式打开文件后如何清空/截断文件?

6

我的代码目前长这样(这些步骤被拆分成多个函数):

/* open file */
FILE *file = fopen(filename, "r+");

if(!file) {

  /* read the file */

  /* modify the data */

  /* truncate file (how does this work?)*/

  /* write new data into file */

  /* close file */
  fclose(file);
}

我知道可以使用"w"模式打开文件,但在这种情况下我不想这么做。我知道在unistd.h / sys/types.h中有一个ftruncate函数,但我不想在代码中使用这些函数,因为我的代码应该具有高度的可移植性(也适用于Windows)。

有没有可能在不关闭/重新打开文件的情况下清除文件?

2个回答

6
使用标准C语言,唯一的方法是每次需要截断时以“w+”模式重新打开文件。您可以使用freopen()实现此目的。 "w+"将继续允许从中读取,因此无需再次以“r+”模式关闭和重新打开。 "w+"的语义是:

打开以进行读写。如果文件不存在,则创建该文件,否则将截断该文件。流定位在文件的开头。

(摘自fopen(3)手册页。)

当使用freopen()时,您可以将文件名参数传递为NULL指针:

my_file = freopen(NULL, "w+", my_file);

如果您不再需要从文件中读取任何内容,那么“w”模式也可以完美地胜任。


1
OP希望得到一个平台无关的解决方案,并且不想重新打开文件。同时仍然使用r+ :) - askmish
1
@askmish 这是不可能的 :-P - Nikos C.
3
使用内核调用会使代码不可移植,就像使用POSIX或w32 API一样。唯一的方法是使用特定于平台的代码。可移植代码(也就是纯ANSI C)无法做到这一点。 - Nikos C.
这对我很有帮助,我不知道你不需要关闭文件。现在我使用了 rewind(file); fopen(filename, "w");。而且我仍然可以使用文件指针 file!如果您能将此嵌入到您的答案中,那就太好了。 - MarcDefiant
@Mogria 我已经更新了答案。然而,正确的方法是使用 freopen() 而不是 fopen()。如果你只是再次使用 fopen(),你会泄漏旧的 FILE(类似于使用 malloc() 分配内存但没有使用 free() 释放它)。这也更容易,因为如果你已经有一个打开的 FILE 句柄,你不需要传递文件名。 - Nikos C.
显示剩余2条评论

3
您可以编写类似于以下的函数(伪代码):
if(this is linux box) 
use truncate()
else if (this is windows box)
use _chsize_s()

这是您需求的最直接解决方案。请参阅msdn.microsoft.com上的man truncate和_chsize_s,同时也要包含必要的头文件。

我知道这会起作用,但只有在真正需要且没有其他方法的情况下才会这样做。 - MarcDefiant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接