Reading a file using fgetc() but characters are skipped. Only when I use fseek() to to move the cursor one step back then it works fine. My issue is I cannot for the life of me wrap my head around it why do I need to use fseek() to solve the problem. I need fresh eyes to explain since my brain is in a lock state.
Code below skips a character
int file_chars = 0;
size_t hdr_size = 15;
char hdr_cook_val[hdr_size];
esp_err_t get_cookie = httpd_req_get_cookie_val(req,COOKIE_NAME,hdr_cook_val,&hdr_size);
if(get_cookie == ESP_ERR_NOT_FOUND && req->uri[0] == '/' && req->method == HTTP_GET){
FILE *index_file = fopen(HTML_PART_FOLDER"/index.txt","r");
char *hdr_val = malloc(sizeof(char)*MALLOC_DEFAULT_SIZE);
if(hdr_val==NULL){ESP_LOGE(TAG,"Malloc failed variable name: hdr_val");return ESP_OK;}
for(int i=0;;i++){
file_chars = fgetc(index_file);
if(file_chars==EOF){
httpd_resp_send_chunk(req,hdr_val,i);
httpd_resp_send_chunk(req,NULL,0);
break;
}
hdr_val[i] = file_chars;
if(i==9999){
httpd_resp_send_chunk(req,hdr_val,i);
i=-1;
vTaskDelay(pdMS_TO_TICKS(20));
}
}
free(hdr_val);
fclose(index_file);
return ESP_OK;
}
using the same code but only adding the line fseek(index_file,ftell(index_file)-1,SEEK_SET);
all is good
int file_chars = 0;
size_t hdr_size = 15;
char hdr_cook_val[hdr_size];
esp_err_t get_cookie = httpd_req_get_cookie_val(req,COOKIE_NAME,hdr_cook_val,&hdr_size);
if(get_cookie == ESP_ERR_NOT_FOUND && req->uri[0] == '/' && req->method == HTTP_GET){
FILE *index_file = fopen(HTML_PART_FOLDER"/index.txt","r");
char *hdr_val = malloc(sizeof(char)*MALLOC_DEFAULT_SIZE);
if(hdr_val==NULL){ESP_LOGE(TAG,"Malloc failed variable name: hdr_val");return ESP_OK;}
for(int i=0;;i++){
file_chars = fgetc(index_file);
if(file_chars==EOF){
httpd_resp_send_chunk(req,hdr_val,i);
httpd_resp_send_chunk(req,NULL,0);
break;
}
hdr_val[i] = file_chars;
if(i==9999){
httpd_resp_send_chunk(req,hdr_val,i);
fseek(index_file,ftell(index_file)-1,SEEK_SET);
i=-1;
vTaskDelay(pdMS_TO_TICKS(20));
}
}
free(hdr_val);
fclose(index_file);
return ESP_OK;
}
The code loads until the 10,000th character, then only sends 9999 of them.
Try this:
int i = 0;
for( ;; ) {
file_chars = fgetc(index_file);
if( file_chars == EOF ) {
httpd_resp_send_chunk(req,hdr_val,i);
httpd_resp_send_chunk(req,NULL,0);
break;
}
hdr_val[ i ] = file_chars;
// count that character and test for complete batch
if( ++i == 10000 ) {
httpd_resp_send_chunk( req, hdr_val, i ); // Send 10000 per batch
i = 0;
vTaskDelay(pdMS_TO_TICKS(20));
}
}
And, learn to use the spacebar... Dense code is both difficult to read and provides shelter for bugs.
EDIT:
On reflection, if the source file is an exact multiple of 10000, the code above will send two empty 'chunks'. This is not good! The following is more compact while fixing that problem. PLUS, 10000
is a magic number that should be identified somehow.
#define BYTES_PER_OUT_CHUNK 10000 // why 10000? Why not...
int i = 0;
while( ( file_chars = fgetc( index_file ) ) != EOF ) {
hdr_val[ i++ ] = file_chars;
if( i == BYTES_PER_OUT_CHUNK ) {
httpd_resp_send_chunk( req, hdr_val, i );
i = 0;
vTaskDelay( pdMS_TO_TICKS( 20 ) );
}
}
if( i )
httpd_resp_send_chunk( req, hdr_val, i );
httpd_resp_send_chunk( req, NULL, 0 );