How to Read a Growing Text File in C++

How to read a growing text file in C++?

Since none of these answers worked, i came up with one that does work...

#include <iostream>
#include <string>
#include <fstream>

using namespace std;

int main()
{
string log, logFile("test.txt");
std::streamoff p = 0;
ifstream ifs(logFile.c_str());

while(true)
{

ifs.seekg(p); //*1
while (getline(ifs, log))
{
cout << log << endl;
if(ifs.tellg() == -1) p = p + log.size();
else p = ifs.tellg();
}
ifs.clear();

}
}

Reading a growing file

Yes. You can call clearerr on the file, or perform any seek opereration such as fseek(f, 0, SEEK_CUR).

Reading integer to a text file in C (integer is present in a structure)

I guess you are trying to read the file using a text editor.

Issue is with fwrite:
"fwrite" will write the numbers without converting it to ASCII or utf-8 chars hence numbers won't be found when opened via file editor. Instead, you will find a characters equivalent of the numbers stored. Try reading the file using "fread" you will get the actual values back into the "employee_details" structure.

Incase you want to read the data via file editor: use fprint

Try something Like:
fprintf(p_wfile , "%s %d\n", employee.name, employee.id);

Read a text file into a struct array with functions

I'd compile with -Wall -O2 to catch warnings, which would have pointed out an error.

In your fscanf and printf, you don't want name[100] but name. You want to point to the name array, but name[100] is a single char [fetching past the end of the array (i.e.) undefined behavior], and would be flagged by the compiler.

Here's a version of your code with the bugs annotated/corrected:

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

typedef struct {
char name[100];
int age;
float height;
} PERSON;

void StoreInArray(PERSON * X, FILE * f, int lines);

int
main()
{
PERSON *X = NULL;
FILE *f;
char ch;
int lines = 1;

f = fopen("filename.txt", "r");

while ((ch = fgetc(f)) != EOF) {
if (ch == '\n')
lines++;
}

rewind(f);

X = (PERSON *) malloc((lines / 3) * sizeof(PERSON));

StoreInArray(X, f, lines);

return 0;
}

void
StoreInArray(PERSON * X, FILE * f, int lines)
{
int i = 0;

for (i = 0; i < lines / 3; i++) {
#if 0
fscanf(f, "%s%d%f", (*(X + i)).name[100], &(*(X + i)).age, &(*(X + i)).height);
#else
fscanf(f, "%s%d%f", (*(X + i)).name, &(*(X + i)).age, &(*(X + i)).height);
#endif
}

//for testing//
for (i = 0; i < lines / 3; i++) {
#if 0
printf("%s\n%d \n%f\n", X[i].name[100], X[i].age, X[i].height);
#else
printf("%s\n%d \n%f\n", X[i].name, X[i].age, X[i].height);
#endif
}
}

Note that using *(X + i)).name is cumbersome, so here's a simplified and more readable version that uses an extra pointer variable:

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

typedef struct {
char name[100];
int age;
float height;
} PERSON;

void StoreInArray(PERSON * X, FILE * f, int lines);

int
main()
{
PERSON *X = NULL;
FILE *f;
char ch;
int lines = 1;

f = fopen("filename.txt", "r");

while ((ch = fgetc(f)) != EOF) {
if (ch == '\n')
lines++;
}

rewind(f);

X = (PERSON *) malloc((lines / 3) * sizeof(PERSON));

StoreInArray(X, f, lines);

return 0;
}

void
StoreInArray(PERSON * X, FILE * f, int lines)
{
int i = 0;
PERSON *p;

p = X;
for (i = 0; i < lines / 3; i++, p++)
fscanf(f, "%s%d%f", p->name, &p->age, &p->height);

//for testing//
p = X;
for (i = 0; i < lines / 3; i++, p++)
printf("%s\n%d \n%f\n", p->name, p->age, p->height);
}

It isn't really necessary to preread the file to get a line count. It is possible to grow your array dynamically, as lines are read in, using realloc:

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

typedef struct {
char name[100];
int age;
float height;
} PERSON;

int
main()
{
PERSON *X = NULL;
FILE *f;
int i;
PERSON *p;
int count = 0;

f = fopen("filename.txt", "r");

while (1) {
X = realloc(X,sizeof(PERSON) * (count + 1));
p = &X[count];

if (fscanf(f, "%s%d%f", p->name, &p->age, &p->height) == EOF)
break;

++count;
}

fclose(f);

// trim the array
X = realloc(X,sizeof(PERSON) * count);

p = X;
for (i = 0; i < count; i++, p++)
printf("%s\n%d \n%f\n", p->name, p->age, p->height);

return 0;
}

Here's a further refinement that reduces the number of realloc calls needed:

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

typedef struct {
char name[100];
int age;
float height;
} PERSON;

int
main()
{
PERSON *X = NULL;
FILE *f;
int i;
PERSON *p;
size_t count = 0;
size_t alloc = 0;

f = fopen("filename.txt", "r");

while (1) {
if (count >= alloc) {
alloc += 100;
X = realloc(X,sizeof(PERSON) * alloc);
}

p = &X[count];

if (fscanf(f, "%s%d%f", p->name, &p->age, &p->height) == EOF)
break;

++count;
}

fclose(f);

// trim the array to what was actually used
X = realloc(X,sizeof(PERSON) * count);

p = X;
for (i = 0; i < count; i++, p++)
printf("%s\n%d \n%f\n", p->name, p->age, p->height);

return 0;
}

Read from a growing file in C#?

You can do this, but you need to keep careful track of the file read and write positions using Stream.Seek and with appropriate synchronization between the threads. Typically you would use an EventWaitHandle or subclass thereof to do the synchronization for data, and you would also need to consider synchronization for the access to the FileStream object itself (probably via a lock statement).

Update: In answering this question I implemented something similar - a situation where a file was being downloaded in the background and also being uploaded at the same time. I used memory buffers, and posted a gist which has working code. (It's GPL but that might not matter for you - in any case you can use the principles to do your own thing.)



Related Topics



Leave a reply



Submit