Reading a file and storing all the data in a buffer
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
2
down vote
favorite
I wrote a function to read the entire content of a file and return a pointer to an allocated bufer containing all the data.
Please could you tell me if there is a better way of doing this ? One solution could be to use stat()
to pre-allocate a buffer and do only one read()
call but I don't know if it's better, any though ?
#include <stdio.h>
#include <memory.h>
char *file_read(const char *path, size_t *file_size)
FILE *file = fopen(path, "r");
char buffer[FILE_READ_BUFFER_SIZE];
char *tmp = NULL;
char *data = NULL; // The buffer containing the data of the file
char *data_cursor = NULL; // The current position in the data buffer
size_t data_size = 0; // The size of the data buffer
size_t n = 0; // The number of bytes read by fread()
if (file == NULL)
goto error;
while ((n = fread(buffer, sizeof(char), sizeof(buffer), file)) > 0)
if (data == NULL)
data = malloc(sizeof(char) * n);
data_cursor = data;
data_size = n;
else
// We compute the position in the buffer as an integer
// to be able to re-apply after realloc(). Because realloc()
// can move the pointer we need this position as an integer.
size_t cursor_pos = data_cursor - data;
tmp = realloc(data, sizeof(char) * data_size + n);
if (tmp == NULL)
goto error;
data = tmp;
data_cursor = data + cursor_pos;
data_size += n;
memcpy(data_cursor, buffer, n);
if (ferror(file))
goto error;
fclose(file);
if (file_size != NULL)
*file_size = data_size;
return data;
error:
if (file != NULL)
fclose(file);
if (data != NULL)
free(data);
return NULL;
c
add a comment |Â
up vote
2
down vote
favorite
I wrote a function to read the entire content of a file and return a pointer to an allocated bufer containing all the data.
Please could you tell me if there is a better way of doing this ? One solution could be to use stat()
to pre-allocate a buffer and do only one read()
call but I don't know if it's better, any though ?
#include <stdio.h>
#include <memory.h>
char *file_read(const char *path, size_t *file_size)
FILE *file = fopen(path, "r");
char buffer[FILE_READ_BUFFER_SIZE];
char *tmp = NULL;
char *data = NULL; // The buffer containing the data of the file
char *data_cursor = NULL; // The current position in the data buffer
size_t data_size = 0; // The size of the data buffer
size_t n = 0; // The number of bytes read by fread()
if (file == NULL)
goto error;
while ((n = fread(buffer, sizeof(char), sizeof(buffer), file)) > 0)
if (data == NULL)
data = malloc(sizeof(char) * n);
data_cursor = data;
data_size = n;
else
// We compute the position in the buffer as an integer
// to be able to re-apply after realloc(). Because realloc()
// can move the pointer we need this position as an integer.
size_t cursor_pos = data_cursor - data;
tmp = realloc(data, sizeof(char) * data_size + n);
if (tmp == NULL)
goto error;
data = tmp;
data_cursor = data + cursor_pos;
data_size += n;
memcpy(data_cursor, buffer, n);
if (ferror(file))
goto error;
fclose(file);
if (file_size != NULL)
*file_size = data_size;
return data;
error:
if (file != NULL)
fclose(file);
if (data != NULL)
free(data);
return NULL;
c
1
Code posted to codereview should compile, it would be great if you could make this a complete file especially could you post the code forerror_set_from_errno_ptr()
?
â Harald Scheirich
Jan 24 at 13:45
It's just a utility function which stores internally the last errrno & strerror() and return NULL. I replaced it with return NULL in my example. Thanks !
â Thibaut D.
Jan 24 at 14:48
Here you find how to find size of a file using fseek+ftell, and then allocating a buffer that exact size: stackoverflow.com/questions/5957845/⦠After that use rewind and fread.
â Andreas
Jan 24 at 18:46
add a comment |Â
up vote
2
down vote
favorite
up vote
2
down vote
favorite
I wrote a function to read the entire content of a file and return a pointer to an allocated bufer containing all the data.
Please could you tell me if there is a better way of doing this ? One solution could be to use stat()
to pre-allocate a buffer and do only one read()
call but I don't know if it's better, any though ?
#include <stdio.h>
#include <memory.h>
char *file_read(const char *path, size_t *file_size)
FILE *file = fopen(path, "r");
char buffer[FILE_READ_BUFFER_SIZE];
char *tmp = NULL;
char *data = NULL; // The buffer containing the data of the file
char *data_cursor = NULL; // The current position in the data buffer
size_t data_size = 0; // The size of the data buffer
size_t n = 0; // The number of bytes read by fread()
if (file == NULL)
goto error;
while ((n = fread(buffer, sizeof(char), sizeof(buffer), file)) > 0)
if (data == NULL)
data = malloc(sizeof(char) * n);
data_cursor = data;
data_size = n;
else
// We compute the position in the buffer as an integer
// to be able to re-apply after realloc(). Because realloc()
// can move the pointer we need this position as an integer.
size_t cursor_pos = data_cursor - data;
tmp = realloc(data, sizeof(char) * data_size + n);
if (tmp == NULL)
goto error;
data = tmp;
data_cursor = data + cursor_pos;
data_size += n;
memcpy(data_cursor, buffer, n);
if (ferror(file))
goto error;
fclose(file);
if (file_size != NULL)
*file_size = data_size;
return data;
error:
if (file != NULL)
fclose(file);
if (data != NULL)
free(data);
return NULL;
c
I wrote a function to read the entire content of a file and return a pointer to an allocated bufer containing all the data.
Please could you tell me if there is a better way of doing this ? One solution could be to use stat()
to pre-allocate a buffer and do only one read()
call but I don't know if it's better, any though ?
#include <stdio.h>
#include <memory.h>
char *file_read(const char *path, size_t *file_size)
FILE *file = fopen(path, "r");
char buffer[FILE_READ_BUFFER_SIZE];
char *tmp = NULL;
char *data = NULL; // The buffer containing the data of the file
char *data_cursor = NULL; // The current position in the data buffer
size_t data_size = 0; // The size of the data buffer
size_t n = 0; // The number of bytes read by fread()
if (file == NULL)
goto error;
while ((n = fread(buffer, sizeof(char), sizeof(buffer), file)) > 0)
if (data == NULL)
data = malloc(sizeof(char) * n);
data_cursor = data;
data_size = n;
else
// We compute the position in the buffer as an integer
// to be able to re-apply after realloc(). Because realloc()
// can move the pointer we need this position as an integer.
size_t cursor_pos = data_cursor - data;
tmp = realloc(data, sizeof(char) * data_size + n);
if (tmp == NULL)
goto error;
data = tmp;
data_cursor = data + cursor_pos;
data_size += n;
memcpy(data_cursor, buffer, n);
if (ferror(file))
goto error;
fclose(file);
if (file_size != NULL)
*file_size = data_size;
return data;
error:
if (file != NULL)
fclose(file);
if (data != NULL)
free(data);
return NULL;
c
edited Jan 24 at 14:47
asked Jan 24 at 11:04
Thibaut D.
757
757
1
Code posted to codereview should compile, it would be great if you could make this a complete file especially could you post the code forerror_set_from_errno_ptr()
?
â Harald Scheirich
Jan 24 at 13:45
It's just a utility function which stores internally the last errrno & strerror() and return NULL. I replaced it with return NULL in my example. Thanks !
â Thibaut D.
Jan 24 at 14:48
Here you find how to find size of a file using fseek+ftell, and then allocating a buffer that exact size: stackoverflow.com/questions/5957845/⦠After that use rewind and fread.
â Andreas
Jan 24 at 18:46
add a comment |Â
1
Code posted to codereview should compile, it would be great if you could make this a complete file especially could you post the code forerror_set_from_errno_ptr()
?
â Harald Scheirich
Jan 24 at 13:45
It's just a utility function which stores internally the last errrno & strerror() and return NULL. I replaced it with return NULL in my example. Thanks !
â Thibaut D.
Jan 24 at 14:48
Here you find how to find size of a file using fseek+ftell, and then allocating a buffer that exact size: stackoverflow.com/questions/5957845/⦠After that use rewind and fread.
â Andreas
Jan 24 at 18:46
1
1
Code posted to codereview should compile, it would be great if you could make this a complete file especially could you post the code for
error_set_from_errno_ptr()
?â Harald Scheirich
Jan 24 at 13:45
Code posted to codereview should compile, it would be great if you could make this a complete file especially could you post the code for
error_set_from_errno_ptr()
?â Harald Scheirich
Jan 24 at 13:45
It's just a utility function which stores internally the last errrno & strerror() and return NULL. I replaced it with return NULL in my example. Thanks !
â Thibaut D.
Jan 24 at 14:48
It's just a utility function which stores internally the last errrno & strerror() and return NULL. I replaced it with return NULL in my example. Thanks !
â Thibaut D.
Jan 24 at 14:48
Here you find how to find size of a file using fseek+ftell, and then allocating a buffer that exact size: stackoverflow.com/questions/5957845/⦠After that use rewind and fread.
â Andreas
Jan 24 at 18:46
Here you find how to find size of a file using fseek+ftell, and then allocating a buffer that exact size: stackoverflow.com/questions/5957845/⦠After that use rewind and fread.
â Andreas
Jan 24 at 18:46
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
2
down vote
accepted
I recommend to pass a file pointer rather than a path. This will enable the code to work with streams as well. It would also simplify the awkward error handling.
Modern c allows, and recommends, to declare variables closer to their use.
It is OK to
realloc
even whendata
isNULL
.sizeof(char)
is guaranteed to be1
.Incrementing
data_size
aftermemcpy
lets you dropdata_cursor
andcursor_pos
, which IMHO obfuscate the code. You'd need tomemcpy(data + data_size, buffer, n);
data_size += n;Allocating an array on the stack is usually not recommended. Consider reading directly into
data + data_size
, and get away withoutbuffer
andmemcpy
.
Thanks a lot for those comments, which totally make sense.
â Thibaut D.
Jan 24 at 20:10
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
I recommend to pass a file pointer rather than a path. This will enable the code to work with streams as well. It would also simplify the awkward error handling.
Modern c allows, and recommends, to declare variables closer to their use.
It is OK to
realloc
even whendata
isNULL
.sizeof(char)
is guaranteed to be1
.Incrementing
data_size
aftermemcpy
lets you dropdata_cursor
andcursor_pos
, which IMHO obfuscate the code. You'd need tomemcpy(data + data_size, buffer, n);
data_size += n;Allocating an array on the stack is usually not recommended. Consider reading directly into
data + data_size
, and get away withoutbuffer
andmemcpy
.
Thanks a lot for those comments, which totally make sense.
â Thibaut D.
Jan 24 at 20:10
add a comment |Â
up vote
2
down vote
accepted
I recommend to pass a file pointer rather than a path. This will enable the code to work with streams as well. It would also simplify the awkward error handling.
Modern c allows, and recommends, to declare variables closer to their use.
It is OK to
realloc
even whendata
isNULL
.sizeof(char)
is guaranteed to be1
.Incrementing
data_size
aftermemcpy
lets you dropdata_cursor
andcursor_pos
, which IMHO obfuscate the code. You'd need tomemcpy(data + data_size, buffer, n);
data_size += n;Allocating an array on the stack is usually not recommended. Consider reading directly into
data + data_size
, and get away withoutbuffer
andmemcpy
.
Thanks a lot for those comments, which totally make sense.
â Thibaut D.
Jan 24 at 20:10
add a comment |Â
up vote
2
down vote
accepted
up vote
2
down vote
accepted
I recommend to pass a file pointer rather than a path. This will enable the code to work with streams as well. It would also simplify the awkward error handling.
Modern c allows, and recommends, to declare variables closer to their use.
It is OK to
realloc
even whendata
isNULL
.sizeof(char)
is guaranteed to be1
.Incrementing
data_size
aftermemcpy
lets you dropdata_cursor
andcursor_pos
, which IMHO obfuscate the code. You'd need tomemcpy(data + data_size, buffer, n);
data_size += n;Allocating an array on the stack is usually not recommended. Consider reading directly into
data + data_size
, and get away withoutbuffer
andmemcpy
.
I recommend to pass a file pointer rather than a path. This will enable the code to work with streams as well. It would also simplify the awkward error handling.
Modern c allows, and recommends, to declare variables closer to their use.
It is OK to
realloc
even whendata
isNULL
.sizeof(char)
is guaranteed to be1
.Incrementing
data_size
aftermemcpy
lets you dropdata_cursor
andcursor_pos
, which IMHO obfuscate the code. You'd need tomemcpy(data + data_size, buffer, n);
data_size += n;Allocating an array on the stack is usually not recommended. Consider reading directly into
data + data_size
, and get away withoutbuffer
andmemcpy
.
answered Jan 24 at 19:04
vnp
36.6k12991
36.6k12991
Thanks a lot for those comments, which totally make sense.
â Thibaut D.
Jan 24 at 20:10
add a comment |Â
Thanks a lot for those comments, which totally make sense.
â Thibaut D.
Jan 24 at 20:10
Thanks a lot for those comments, which totally make sense.
â Thibaut D.
Jan 24 at 20:10
Thanks a lot for those comments, which totally make sense.
â Thibaut D.
Jan 24 at 20:10
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f185869%2freading-a-file-and-storing-all-the-data-in-a-buffer%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
1
Code posted to codereview should compile, it would be great if you could make this a complete file especially could you post the code for
error_set_from_errno_ptr()
?â Harald Scheirich
Jan 24 at 13:45
It's just a utility function which stores internally the last errrno & strerror() and return NULL. I replaced it with return NULL in my example. Thanks !
â Thibaut D.
Jan 24 at 14:48
Here you find how to find size of a file using fseek+ftell, and then allocating a buffer that exact size: stackoverflow.com/questions/5957845/⦠After that use rewind and fread.
â Andreas
Jan 24 at 18:46