Reading a file with variable line length line by line in c

Is there a way in C to read a text file line by line without knowing how much space is allocated for it?

here is an example of what i mean:

fgets(line, <dynamic line size>, fileHandle); 

Thanks for the help!

+4
source share
7 answers

Nothing automated. You need to continue to build up your buffer and call fgets until you get a new line or EOF.

 // NOTE: not production ready as does not handle memory allocation failures size_t alloced = 128; char *p = malloc(alloced); char *walk = p; size_t to_read = alloced; for (;;) { if (fgets(walk, to_read, fp) == NULL) break; if (walk[strlen(walk) - 1] == '\n') break; to_read = alloced; alloced *= 2; p = realloc(p, allocated); walk = p + to_read; } 
+5
source

If you have glibc or another libc that supports POSIX (2008), you can use getline :

 ssize_t getline(char **lineptr, size_t *n, FILE *stream); 

getline () reads an entire line from a stream that stores the address of the buffer containing the text in * Lineptr. The buffer has zero completion and includes a newline if it was found.

If * lineptr is NULL, then getline () will allocate a buffer to hold the line to be freed by the user program. (The value in * n is equally ignored.)

+2
source

Basically, you should allocate a temporary buffer of arbitrary size. Then you must scan the input for the newline character, filling the buffer with the scanned characters. If the buffer is full, select a new, larger buffer, copy the old contents to the new buffer, and free the old buffer.

There is a g_io_channel_read_line function in the Glib library that does this for you.

+1
source

Not directly.

To solve this problem, you should be prepared to handle fgets crash if the buffer is not large enough. Start with the malloc ing line to a reasonable start buffer (say 256 characters), then realloc twice as many as every time fgets returns NULL.

0
source

For your "dynamic line size", simply use whatever maximum memory you want to use. If the line is not completed, process the part that you used and perform some additional operations until you reach the end of the line. Use strlen to determine if you have read the whole line.

 void ProcessFile( FILE *fp ) { int len = 0; char lineBuf[ MAX_SIZE ]; while( !feof(fp) ) { do { if( fgets( lineBuf, MAX_SIZE, fp ) > 0 ) { fputs( lineBuf, STDOUT ); len = strlen( lineBuf ); } } while( !feof(fp) && lineBuf[len-1] != '\n' ); puts( "A line has been processed!" ); } return; } 
0
source
 char *myGetLine(FILE *pFile) { //Allocation a chunk of memory. //Read a chunk from the file. //While not a full line then reallocate a bigger chunk of memory and get the next chunk from the file. //NOTE: No malloc()/realloc() error checking is done here. //NOTE: Each call allocates a chunk of memory that the user must free(). const int bufIncrSize = 128; //or whatever increment you like int bufSize = bufIncrSize; char *pLine = (char *)malloc(bufIncrSize); pLine[0] = '\0'; //make it an empty string //while not EOF while (fgets(&pLine[strlen(pLine)], bufIncrSize, pFile) != NULL) { // If we got the newline, then we have the whole line if (pLine[strlen(pLine) - 1] == '\n') break; //else get a bigger buffer and try again bufSize += bufIncrSize; pLine = (char *)realloc(pLine, bufSize); } return pLine; //NOTE the user is responsible for freeing the line buffer } 
0
source

You read a fragment of a line at a time into a buffer of a fixed size, and then copied the contents of that fixed size to a buffer with dynamically allocated and resizable:

 #include <string.h> #include <stdio.h> #include <stdlib.h> #define SIZE ... // some reasonable size to handle most cases int getNextLine(FILE *stream, char **line, size_t *lineLength) { char inbuf[SIZE]; int done = 0; int rval = 1; // success *lineLength = 0; /** * If *line is not NULL, it is assumed that it was allocated on a * previous call to getNextLine. Free it and set to NULL. */ if (*line != NULL) { free(*line); *line = NULL; } while(!done) { char *tmp; if (fgets(inbuf, sizeof inbuf, stream)) { /** * Check for newline character. If present, clear it and set the * done flag to true. */ char *newline = strchr(inbuf, '\n'); if (newline != NULL) { *newline = 0; done = 1; } /** * Extend the dynamic buffer by the length of the input string * and copy the input string to it. */ tmp = realloc(*line, *lineLength + strlen(inbuf) + 1); if (tmp) { *line = tmp; (*line)[*lineLength] = 0; strcat(*line, inbuf); *lineLength += strlen(inbuf) + 1; } else { printf("Error allocating or extending buffer\n"); rval = 0; done = 1; } } else { if (feof(stream)) { printf("At end-of-file\n"); rval = EOF; } else { printf("Error during read\n"); rval = 0; } done = 1; } } return rval; } int main(void) { char *line = NULL; // line *MUST* be initialized to NULL size_t lineLength = 0; int status; for (;;) { int status = getNextLine(stdin, &line, &lineLength); if (status == 0 || status == EOF) break; printf("Read %lu characters in line: \"%s\"\n", (unsigned long) lineLength, line); } return 0; } 
0
source

Source: https://habr.com/ru/post/1313425/


All Articles