Aaron
Aaron

Reputation: 21

Reading a file in at once rather than line by line (in c)

I am trying to read a file into a string all at once, however I have only been able to read it in line by line with this code:

int main()
{
    char input[1000000];
    FILE *fPointer;

    fPointer = fopen("/Users/boys/users.json", "r");

    if( fPointer != NULL)
    {
        while(!feof(fPointer))
        {
            fgets(input, 1000000, fPointer);
            //printf("%s", input);

        }

    }
    printf("%s", input);

    return 0;
}

I am dealing with a json file and have only used csv and simpler files in the past with c as I am still quite new to it and not all that good so if anyone has a simple solution to reading a file in all at once rather than line by line that would be a great help, thanks!

Upvotes: 1

Views: 119

Answers (4)

gsamaras
gsamaras

Reputation: 73376

  1. Open the file (FILE *fPointer = fopen("/Users/boys/users.json", "r");).
  2. Seek it to the end (fseek(fPointer , 0, SEEK_END);).
  3. Get the file position (which is equal to the size).
  4. Rewind the file position.
  5. Allocate the memory needed.
  6. Read file into allocated memory.
  7. Use the string.
  8. De-allocate the memory when you are done.

PS: Reading the file via fread() does not form a string as it may lack a null character (but you can always insert it yourself).

Upvotes: 1

kocica
kocica

Reputation: 6467

fgets() function reads until it reach EOF / NewLine / Specified size. So its not right function to use because you can read max one line if file contains more than one line.

Here one possible way

First you have to find out size (in bytes) of content in file

fseek(fPointer, 0L, SEEK_END);
long numOfBytes = ftell(fPointer);

Than dynamically allocate buffer big enough for this amount of data. (Since you can use VLA)

char *ptr = calloc(numOfBytes+1, 1);
if (ptr == NULL) // Failed to allocate memory
   { perror("calloc"); exit(EXIT_FAILURE); };

Reset position of indicator to the beginning of file (or reopen file)

fseek(fPointer, 0L, SEEK_SET); // Or use rewind

Now you may read whole content of file using fread.

fread(ptr, sizeof(char), numOfBytes, fPointer);

And clean up

free(ptr);
fclose(fPointer);

Upvotes: 3

Andrew Henle
Andrew Henle

Reputation: 1

On a POSIX-compliant system:

int fd = open( filename, O_RDONLY );

struct stat sb;
fstat( fd, sb );

// by adding one, data can possibly be
// treated as a string, assuming no NULs
// exist in the file's contents
char *data = calloc( sb.st_size + 1, 1 );

size_t totalRead = 0;

while ( totalRead < sb.st_size )
{
    ssize_t bytesRead = read( fd, &( data[ totalRead ] ), sb.st_size - totalRead );
    if ( bytesRead <= 0 )
    {
        break;
    }

    totalRead += bytesRead;
}

I used calloc() to create a zero-filled buffer instead of explicitly setting the last byte to NUL. That makes the actual processing a bit easier to see and understand.

I also left out error checking for the same reason.

Upvotes: 0

From man fgets:

fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte ('\0') is stored after the last character in the buffer.

You can use fread to achieve what you want.

Upvotes: 1

Related Questions