【发布时间】:2010-10-26 18:50:23
【问题描述】:
我正在使用 C 将一些数据写入文件。我想删除文件中以前写入的文本,以防它比我现在写的要长。 我想减小文件的大小或截断到最后。我该怎么做?
【问题讨论】:
我正在使用 C 将一些数据写入文件。我想删除文件中以前写入的文本,以防它比我现在写的要长。 我想减小文件的大小或截断到最后。我该怎么做?
【问题讨论】:
如果您想将文件的先前内容保留到一定长度(长度大于零,其他答案提供),那么 POSIX 为该作业提供了 truncate() 和 ftruncate() 函数。
#include <unistd.h>
int ftruncate(int fildes, off_t length);
int truncate(const char *path, off_t length);
该名称表示主要用途 - 缩短文件。但是如果指定的长度比之前的长度长,文件会增长(零填充)到新的大小。注意ftruncate() 作用于文件描述符,而不是FILE *;你可以使用:
if (ftruncate(fileno(fp), new_length) != 0) ...error handling...
但是,您应该知道,混合文件流 (FILE *) 和文件描述符 (int) 访问单个文件很容易导致混淆 - 请参阅 cmets 了解一些问题。这应该是最后的手段。
不过,出于您的目的,打开时截断可能就是您所需要的,为此,其他人提供的选项就足够了。
对于 Windows,有一个函数 SetEndOfFile() 和一个相关函数 SetFileValidData() 可以做类似的工作,但使用不同的界面。基本上,您会寻找要设置文件结尾的位置,然后调用该函数。
【讨论】:
ftruncate(file no(fp)) 是不安全的。 fp 的内部读写缓冲区都不会被刷新。在刷新写入缓冲区之前调用std::fflush,之后调用std::freopen 重新初始化fp
std::fflush 或 std::freopen;你一定是把它和另一种语言混淆了——大概是 C++。这取决于您所说的“不安全”是什么意思。当然,您会立即跳出文件流的知识,在其背后进行操作。没有什么会刷新缓冲区;在使用ftruncate(fileno(fp)) 之前,您应该使用fflush(fp)。接下来会发生什么取决于您打开文件的方式、是否在下一次操作之前重新定位文件流以及其他详细信息。但是,在 o/s 级别,该文件将被截断。
在 Windows 系统中,没有标题 <unistd.h>,但您可以使用
_chsize( fileno(f), size);
【讨论】:
fileno() 好像是deprecated,现在最好用_fileno()。
这是您的操作系统的功能。标准的 POSIX 方法是:
open("file", O_TRUNC | O_WRONLY);
【讨论】:
如果要在某种 UNIX 风格下运行,这些 API 应该可用:
#include <unistd.h>
#include <sys/types.h>
int truncate(const char *path, off_t length);
int ftruncate(int fd, off_t length);
根据我的 Linux 机器上的“man truncate”,这些都符合 POSIX。请注意,如果您传递的长度大于当前长度,这些调用实际上会增加文件的大小 (!)。
【讨论】:
如果您想截断整个文件,打开文件进行写入即可。否则,您必须打开文件进行读取,并将文件中您要保留的部分读取到临时变量中,然后将其输出到您需要的任何地方。
截断整个文件:
FILE *file = fopen("filename.txt", "w"); //automatically clears the entire file for you.
截断部分文件:
FILE *inFile("filename.txt", "r");
//read in the data you want to keep
fclose(inFile);
FILE *outFile("filename.txt", "w");
//output back the data you want to keep into the file, or what you want to output.
【讨论】:
啊,你编辑了你的帖子,你用的是C。当你打开文件时,像这样用“w+”模式打开它,它会截断它准备写:
FILE* f = fopen("C:\\gabehabe.txt", "w+");
fclose(file);
要在 C++ 中截断文件,您可以简单地为文件创建一个 ofstream 对象,使用 ios_base::trunc 作为文件模式来截断它,如下所示:
ofstream x("C:\\gabehabe.txt", ios_base::trunc);
【讨论】: