【问题标题】:Read a line from text file and delete it从文本文件中读取一行并将其删除
【发布时间】:2013-03-23 10:14:26
【问题描述】:

我想逐行读取文本文件,执行一些检查,如果不需要,删除它。 我已经完成了读取行的代码,但是如果我不需要,我不知道如何删除该行。 请帮我找到删除该行的最简单方法。 这是我尝试过的代码 sn-p:

   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");

【问题讨论】:

  • 将整个文件读入内存并写出除要删除的行之外的所有内容。
  • 看起来很复杂:(你能举个例子吗?
  • 也许你可以试试r+ 模式,你可以读写文件
  • 如果可能的话,你不应该混合Win32C-stdlib。 Win32 提供 ReadFile 并且比使用 fopen 更加一致

标签: c windows file winapi


【解决方案1】:

这是一个例子:

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() 时使用的属性,这可能是一个问题。
  • rename()(或delete())函数是返回错误还是设置了errno
  • 不,不返回错误。我在这里看到两种奇怪的行为。 1. 在 rename() 之前放置 remove() 会在 rename() 文件时出错。 2.rename()后放置remove()不会重命名文件而是生成一个新文件:\
  • 现在还有一个问题,有时 rename() 也会失败,二十次尝试一次。
  • 您也可以尝试在重命名和删除之间调用sleep()。看看那个问题:stackoverflow.com/questions/11021639/…
【解决方案2】:

您可以将所有不包含数字 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" );

【讨论】:

  • 我做了同样的事情,但文件既没有被删除也没有被重命名,但是函数 rename() 成功了。由于我在使用 CreateFile() 时使用的属性,这可能是一个问题。
  • 可能是访问权限问题。检查remove和rename的返回值
  • 是否创建了“File_copy.txt”文件?
  • 是文件已创建。我在这里看到两种奇怪的行为。 1. 在 rename() 之前放置 remove() 会在 rename() 文件时出错。 2.rename()后放置remove()不会重命名文件而是生成一个新文件:\
  • 现在还有一个问题,有时 rename() 也会失败,二十次尝试一次。
【解决方案3】:

另一个解决方案可能是写回同一个文件(写回你读出的内容,除了你不想要的行)并在完成时使用 Windows API 函数SetEndOfFile 截断它。这可能会使代码有点混乱,但您不需要创建文件的第二个副本,因此从磁盘使用的角度来看它更有效。

【讨论】:

    【解决方案4】:

    有很多方法可以解决这个问题,其中之一是,当您到达不想写入的位置时,您可以打开另一个文件进行写入,忽略该绘制并继续写入直到文件结束。以后你可以删除旧文件并用旧文件重命名新文件。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-21
      • 2020-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多