从文本文件中读取一行并删除它。

4

我希望逐行读取文本文件,进行一些检查,如果该行不需要,则删除它。 我已经编写了读取行的代码,但是我不知道如何删除不需要的行。 请帮助我找到最简单的方法来删除该行。 这是我尝试过的代码片段:

   char ip[32];
   int port;
   DWORD dwWritten;
   FILE *fpOriginal, *fpOutput;
   HANDLE hFile,tempFile;
   hFile=CreateFile("Hell.txt",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
   tempFile=CreateFile("temp.txt",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
   WriteFile(hFile,"10.0.1.25 524192\r\n\r\n10.0.1.25 524193\r\n\r\n",strlen("10.0.1.25 524192\r\n\r\n10.0.1.25 524193\r\n\r\n"),&dwWritten,0);
   fpOriginal = fopen("Hell.txt", "r+");
   fpOutput = fopen("temp.txt", "w+");

   while (fscanf(fpOriginal, " %s %d", ip, &port) > 0) 
      {
         printf("\nLine1:");
         printf("ip: %s, port: %d", ip, port);
         char portbuff[32], space[]=" ";
         sprintf(portbuff, "%i",port);
         strcat(ip," ");
         strcat(ip,portbuff);
         if(port == 524192)
            printf("\n Delete this Line now");
         else
            WriteFile(tempFile,ip,strlen(ip),&dwWritten,0);
      }

     fclose(fpOriginal);
     fclose(fpOutput);
     CloseHandle(hFile);
     CloseHandle(tempFile);
     remove("Hell.txt");
     if(!(rename("temp.txt","Bye.txt")))
     {
         printf("\ncould not rename\n");
     }
     else 
        printf("\nRename Done\n");
     //remove ("Hell.txt");

3
将整个文件读入内存,然后将除你想删除的行外的所有内容写出。 - Patashu
看起来很复杂 :( 你能给一些例子吗? - Ayse
1
也许你可以尝试使用 r+ 模式,这样你就可以读取并写入文件了。 - Koushik Shetty
1
如果可能的话,您不应该混合使用Win32C标准库。Win32提供了ReadFile功能,并且与使用fopen相比更为一致。 - bash.d
4个回答

4

这里有一个例子:

char* inFileName = "test.txt";
char* outFileName = "tmp.txt";
FILE* inFile = fopen(inFileName, "r");
FILE* outFile = fopen(outFileName, "w+");
char line [1024]; // maybe you have to user better value here
int lineCount = 0;

if( inFile == NULL )
{
    printf("Open Error");
}

while( fgets(line, sizeof(line), inFile) != NULL )
{
    if( ( lineCount % 2 ) != 0 )
    {
        fprintf(outFile, "%s", line);
    }

    lineCount++;
}


fclose(inFile);
fclose(outFile);

// possible you have to remove old file here before
if( !rename(inFileName, outFileName) )
{
    printf("Rename Error");
}

我也尝试了同样的方法,但即使函数rename()成功执行,文件仍未被删除或重命名。这可能是由于我在使用CreateFile()时使用的属性引起的问题吗? - Ayse
1
rename()(或delete())函数是否返回错误或设置了errno - ollo
1
没有返回错误。我在这里看到两个奇怪的行为。
  1. 在重命名文件时,将remove()放在rename()之前会导致错误。
  2. 将remove()放在rename()之后不会重命名文件,但会生成一个新文件:\
- Ayse
现在又出现了另一个问题,有时候 rename() 也会失败,在二十次尝试中有一次。 - Ayse
2
你也可以在重命名和删除之间尝试使用 sleep() 调用。请参考这个问题:http://stackoverflow.com/questions/11021639/overwriting-files-in-windows-by-renaming-randomly-fails - user2127352
显示剩余2条评论

1
另一种解决方案可能是将内容写回到同一个文件中(除了不需要的行之外,写回读取出来的内容),并在完成时使用Windows API函数SetEndOfFile截断它。这可能会更加混乱,但您不需要创建文件的第二个副本,因此在磁盘使用方面更有效率。

1

解决这个问题的方法有很多种,其中之一是,在达到不想写入的点时,可以打开另一个文件进行写入,省略该部分并继续写入直至文件结尾。最后,您可以删除旧文件并将新文件重命名为旧文件。

if(number == 2)
{
     continue;
}
else
{
    writetofilefunction()
}

1
你可以将不包含数字2的所有行复制到一个新文件中,然后使用新文件代替旧文件。
fp = fopen("File.txt", "r");
fp2 = fopen("File_copy.txt", "w");
while (fscanf(fp, " %s %d", string, &number) > 0) {
        if(number != 2)
        {
             fprintf(fp2, "%s %d\n", string, number);
        }
}
close(fp);
close(fp2);
remove("File.txt");
rename( "File_copy.txt", "File.txt" );

可能是访问权限问题。请检查删除和重命名返回的值。 - MOHAMED
“File_copy.txt” 文件已创建吗? - MOHAMED
是的,文件已创建。我在这里看到两个奇怪的行为。
  1. 在rename()之前放置remove()会导致重命名文件时出错。
  2. 在rename()之后放置remove()不会重命名文件,但会生成一个新文件:\
- Ayse
现在又出现了另一个问题,有时候 rename() 也会失败,在二十次尝试中有一次。 - Ayse
我更新了我的问题并添加了我正在尝试的最新代码。 - Ayse
显示剩余3条评论

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