所以我有一个大文件,一旦它达到一定的大小,我想完全删除前半部分,并将后半部分下移,有效地使其大小减半。以下是我的想法:
FILE *fp, *start;
int ch, block_length, filesize;
char c;
//open the file and initialize pointers
fp = fopen(FILEPATH, "rb+");
start = fp;
rewind(start);
//Check the size of the file
fseek(fp, 0, SEEK_END);
filesize = ftell(fp);
if(filesize >= LOG_MAX_FILE_SIZE)
{
//Go to middle of file
fseek(fp, (-1) * LOG_MAX_FILE_SIZE/2, SEEK_END);
//Go forwards until you get a new line character to avoid cutting a line in half
for(;;)
{
//Read char
fread(&ch, 1, 1, fp);
//Advance pointer
fseek(fp, 1, SEEK_CUR);
if( (char)ch == 'n' || ch == EOF)
break;
}
//fp is now after newline char roughly in middle of file
//Loop over bytes and put them at start of file until EOF
for(;;)
{
//Read char
fread(&ch, 1, 1, fp);
//Advance pointer
fseek(fp, 1, SEEK_CUR);
if(ch != EOF)
{
c = (char)ch;
fwrite(&c,1,1,start);
fflush(start);
//Advance start
fseek(start, 1, SEEK_CUR);
}
else
break;
}
//Calculate length of this new file
block_length = ftell(start);
//Go back to start
rewind(start);
//Truncate file to block length
ftruncate(fileno(start), block_length);
}
但是,这似乎在做一些非常非常奇怪的事情(用"f"填充文件,混淆其中的行和一些字符等)。有人知道我在这段代码中可能做错了什么吗?事先谢谢!
我认为问题的一部分是您在阅读时使用了fseek
。对fread和fwrite的调用使文件指针前进。如果调用fseek,它将跳过下一个字符。
在下面的代码序列中,fread
调用将读取一个字符,并将当前偏移量提前到下一个字符。随后的fseek
跳过该字符并移动到下一个。所以它会每隔一秒读取一个字符。
fread(&ch, 1, 1, fp);
fseek(fp, 1, SEEK_CUR);
写调用也存在同样的问题(不需要后续的查找)。此外,由于对OP的编辑显示start和fp是相同的值,因此逻辑将不正确(需要单独的文件指针才能使用该逻辑)。
找到开始位置后,您可以将文件复制成大块(比如一次64KB),从尾部读取,然后跳到开始并写入,然后跳回尾部。。。
ftruncate()
是释放空间的最后一步。
考虑让读文件流和写文件流指向同一个文件是否更容易。在单个流上搜索较少(因此代码更简单)。我可能会这么做。