当文件超过 514 字节时,fgets 返回 NULL,C

时间:2021-01-26 08:59:55

标签: c csv fgets

我正在编写一个小程序,它从 csv 文件中读取 n 个最新行,然后将这些行打印到终端。但是我偶然发现了一个我无法弄清楚的问题。 我尝试从文件的顶部和底部开始读取,并使用 \n 和 \r 指示计算行数。

我按照建议将常量从“0x0A”更改为“\n”,并将“-1”更改为宏 EOF。变量“字母”从 char 变为 int。

代码:

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

int main() {
  char *token;
  int i = 3;
  int j = 0;
  int linebreakes = 0;
  char line[200];
  int letter = 0;
  int max_rows = 16;
  int eof = 0;
  char *strings[16];

  FILE *fp;
  fp = fopen("C:\\testCSV\\testfile.csv", "rb");
  printf("j = %d\n", j);

  while (linebreakes < max_rows && eof == 0) {
    fseek(fp, -i, SEEK_END);
    letter = fgetc(fp);
    printf("LINE BREAKES [%d]\n", linebreakes);
    i++;
    printf("i = %d\n", -i);

    if (letter == EOF) {            //EOF, 0xFF, -1
      printf("EOF DETECTED\n");
      fseek(fp, (-i + 2), SEEK_END);
      eof = 1;     //exit while loop
    }

    if (letter == '\n') {                   //0x0A == LF
      printf("/n detected!!\n");
      linebreakes++;
      fseek(fp, -i, SEEK_END);
      letter = fgetc(fp);
    }

    if (letter == '\r') {                   //0x0D == CR
      printf("/r detected!!!\n");
      i++;
    }
  }

  printf("letter = %c on %d\n", letter, i);

  if (!eof) {
    fseek(fp, (-i + 3), SEEK_END);
  }

  printf("The latest %d rows in the file contains the following values: \n\n",
      (linebreakes + 1));

  while (fgets(line, sizeof(line), fp) != NULL) {
    printf("line = %s\n", line);
    token = strtok(line, ",");
    printf("token = [%s] before while != null\n", token);

    while (token != NULL) {
      printf("token = %s\n", token);
      token = strtok(NULL, ",");
      j++;
    }
  }

  if (feof(fp)) {
    printf("end of FILEEEE");
  }

  if (ferror(fp)) {
    printf("error indicator set");
  }

  fclose(fp);
  printf("file closed\n");
}

原理是通过从文件末尾倒退并计算换行符来读取文件中最新的 n 行。请注意,尚未添加错误处理。当换行符达到要求读取的行数时,我开始使用 fgets 从那里读取并挑选要打印的标记。

这很有效,直到我在一行中添加几个字符。然后它只是跳转到 fclose() 并打印“文件关闭”而不打印任何行。我注意到它的工作阈值是文件大小为 514 字节,但这可能是巧合。

如果我向“line”数组添加更多元素,则没有任何变化。 正如您在程序末尾看到的那样,我尝试读取 ferror 是否出错。但我没有收到错误,只有文件结尾。

该文件目前有 16 行,为了让您了解文件的外观,其中包含最少字符的行如下所示:

$1,20210125 12:59,t1,t2,t3

其中包含最多字符的行如下所示:

$11,20210125 14:18,testagain,heyhey,hje

我只需要在第一行添加“a”即可使程序停止工作。 (或任何其他行,都没有关系)

我正在使用 CRLF 行尾的 Windows 操作系统。

我一定是做错了什么,但我不知道是什么,因为我是 C 编程的新手。

当然,我搜索过是否可以找到有类似问题的人。但我没有找到任何可以帮助我的东西。

0 个答案:

没有答案