使用C将文件的前半部分替换为后半部分并截断



所以我有一个大文件,一旦它达到一定的大小,我想完全删除前半部分,并将后半部分下移,有效地使其大小减半。以下是我的想法:

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()是释放空间的最后一步。

考虑让读文件流和写文件流指向同一个文件是否更容易。在单个流上搜索较少(因此代码更简单)。我可能会这么做。

相关内容

  • 没有找到相关文章

最新更新