簡體   English   中英

在C中同時讀取和寫入文件

[英]Reading and writing to a file at the same time in C

假設交換文件中的每兩行,直到只剩下一行或所有行都用盡。 我不想在這樣做時使用其他文件。

這是我的代碼:

#include <stdio.h>

int main() {
    FILE *fp = fopen("this.txt", "r+");
    int i = 0;
    char line1[100], line2[100];
    fpos_t pos;
    fgetpos(fp, &pos);

    //to get the total line count
    while (!feof(fp)) {
        fgets(line1, 100, fp);
        i++;
    }

    i /= 2;  //no. of times to run the loop
    rewind(fp);

    while (i-- > 0) {  //trying to use !feof(fp) condition to break the loop results in an infinite loop
        fgets(line1, 100, fp);
        fgets(line2, 100, fp);

        fsetpos(fp, &pos);

        fputs(line2, fp);
        fputs(line1, fp);

        fgetpos(fp, &pos);
    }

    fclose(fp);
    return 0;
}

aaa
b
cc
ddd
ee  
ffff
gg
hhhh
i
jj

b
aaa
ddd
cc
ddd
c
c

c


i
jj

我甚至嘗試使用fseek代替fgetpos只是為了得到同樣的錯誤結果。

, the cursor is rightfully at 17th byte where it is supposed to be and even the file contents after the 4th line are unchanged and somehow for some reason when fgets is called when the loop is running for the third time, the contents read into arrays line1 and line2 are "c\\n" and "ddd\\n" respectively. 根據我的想法,在第二個while循環運行兩次之后 ,光標正確地位於第17個字節,它應該是甚至第4行之后的文件內容都沒有改變,並且由於某種原因,當循環第三次運行時調用fgets時,讀入數組line1和line2的內容為“c \\ n”和“ddd \\ n”分別。

再次,我不想用另一個文件來完成這個,我只需要弄清楚屏幕背后到底出了什么問題

任何線索將不勝感激。 謝謝。

您的代碼中存在多個問題:

  • 您不檢查fopen()成功,冒着未定義的行為的風險。

  • 確定總行數的循環不正確。
    在這里了解原因: 為什么“while(!feof(file))”總是錯的?

  • 您實際上不需要計算總行數。

  • 在從寫回到讀取之前,應該調用fflush()將內容寫回文件。

C標准為在更新模式下打開的文件指定了此限制:

7.21.5.3 fopen函數

[...]輸出不應直接跟隨輸入而不干預fflush功能或文件定位功能( fseekfsetposrewind ),並且輸入不應直接跟隨輸出而不干預文件定位功能,除非輸入操作遇到文件結尾。

這解釋了為什么在以相反順序寫入行之后讀取文件位置會導致問題。 調用fflush()應該可以解決這個問題。

這是一個更正版本:

#include <stdio.h>

int main(void) {
    FILE *fp;
    char line1[100], line2[100];
    fpos_t pos;

    fp = fopen("this.txt", "r+");
    if (fp == NULL) {
        fprintf(stderr, "cannot open this.txt\n");
        return 1;
    }

    while (fgetpos(fp, &pos) == 0 &&
           fgets(line1, sizeof line1, fp) != NULL &&
           fgets(line2, sizeof line2, fp) != NULL) {

        fsetpos(fp, &pos);
        fputs(line2, fp);
        fputs(line1, fp);
        fflush(fp);    
    }

    fclose(fp);
    return 0;
}

更改文件的當前位置時,可能不一定刷新緩沖區。 所以必須明確刷新它。

例如使用fflush(fp);

更改

fputs(line2,fp);
fputs(line1,fp);

fputs(line2,fp);
fputs(line1,fp);
fflush(fp);

為什么不使用兩個文件指針,兩個指向同一個文件,一個讀取,一個寫入? 無需跟蹤文件位置,無需尋找,無需沖洗。

這種方法可以為您提供許多復雜的東西。 那些不必要的努力更好地投入到如下的一些復雜的錯誤檢查/記錄中;-):

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(void) 
{
  int result = EXIT_SUCCESS;

  size_t blocks = 0;

  int l1_done = 0;
  int l2_done = 0;

  FILE *fpin = fopen("this.txt", "r");
  FILE *fpout = fopen("this.txt", "r+");

  if (NULL == fpin)
  {
    result = EXIT_FAILURE;
    perror("fopen() to for reading failed");
  }    

  if (NULL == fpout)
  {
    result = EXIT_FAILURE;
    perror("fopen() for writing failed");
  }    

  while (EXIT_SUCCESS == result && !l1_done && !l2_done)
  {
    result = EXIT_FAILURE;

    char line1[100];
    char line2[100];

    if ((l1_done = (NULL == fgets(line1, sizeof line1, fpin))))
    {
      if (ferror(fpin))
      {
        fprintf(stderr, "Reading line %zu failed.\n", 2*blocks);
        break;
      }
    }

    if ((l2_done = (NULL == fgets(line2, sizeof line2, fpin))))
    {
      if (ferror(fpin))
      {
        fprintf(stderr, "Reading line %zu failed.\n", 2*blocks + 1);
        break;
      }
    }

    {
      size_t len = strlen(line1);

      if (((sizeof line1 - 1) == len) && ('\n' != line1[len]))
      {
        fprintf(stderr, "Line %zu too long or new-line missing.\n", 2*blocks);
        break;
      } 
    }

    {
      size_t len = strlen(line2);

      if (((sizeof line2 - 1) == len) && ('\n' != line2[len]))
      {
        fprintf(stderr, "Line %zu too long or new-line missing.\n", 2*blocks + 1);
        break;
      }
    } 

    if (!l2_done)
    {
      if (EOF == fputs(line2, fpout))
      {
        fprintf(stderr, "Writing line %zu as line %zu failed.\n", 2*blocks + 1, 2*blocks);
        break;
      }
    } 

    if (!l1_done)
    {
      if (EOF == fputs(line1, fpout))
      {
        fprintf(stderr, "Writing line %zu as line %zu failed.\n", 2*blocks, 2*blocks + 1);
        break;
      } 
    }

    ++blocks;

    result = EXIT_SUCCESS;
  }

  if (EXIT_SUCCESS == result && !ll_done && l2_done)   
  {
    fprintf(stderr, "Odd number of lines.\n");
  }

  fclose(fpin);  /* Perhaps add error checking here as well ... */
  fclose(fpout);  /* Perhaps add error checking here as well ... */

  return result;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM