Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

csv - fgets returns NULL when file exceeds 514 bytes, C

I am writing a small program that read n latest lines from a csv file and then printing these lines to the terminal. But I stumbled upon a problem that I cant figure out. I have tried starting to read from the top and bottom of the file and counting rows with the and indications.

I changed the constants from "0x0A" to ' ' and changed "-1" to the macro EOF as suggested. The variable "letter" is changed from char to int.

The code:

#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
", j);

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

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

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

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

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

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

  printf("The latest %d rows in the file contains the following values: 

",
      (linebreakes + 1));

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

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

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

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

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

The philosophy is to read the n latest lines in the file by going backwards from the end of the file and counting the line-breaks. Note that the error handling is not yet added. When line-breaks hit the requested amount of lines to be read, I start reading with fgets from there and pick out tokens to print.

This works well, until I add a few chars to a line. Then it just jumps to fclose() and prints "file closed" without printing any lines at all. I have noticed that the threshold for it to work is on 514 bytes in file size, but this might be a coincidence.

There's no change if I add more elements to the "line" array. As you can see at the end of the program, I try to read if I get an error with ferror. But I don't get an error, only end of file.

The file is at 16 rows at the moment, and for you to get an idea how the file looks, the line with fewest chars in it looks like this:

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

and the line with the most chars in it looks like this:

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

I only need to add 'a' to the first line to make the program stop working. (or any other line, it does not matter)

I am working on Windows OS with CRLF on line endings.

I must've done something wrong but I cannot figure out what as I am new to C programming.

Of course I searched to see if I could find anyone with a similar problem. But I did not find anything that could help me.

question from:https://stackoverflow.com/questions/65898407/fgets-returns-null-when-file-exceeds-514-bytes-c

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...