How to assign text file data to variable - c

I am trying to read from a text file and assign that to a variable. At the moment I have it at the stage where it reads from the file and prints it out, however I haven't figured out how to assign the result to a variable.
This is my code:
int c;
FILE *file;
file = fopen(inputFilename, "r");
if (file) {
while ((c = getc(file)) != EOF) {
putchar(c);
}
fclose(file);
}
I'm not entirely sure what putchar(c) means but I assume it is just printing out the characters one at a time?
How would I go about trying to achieve what I am looking to do?

What you mean is to get the whole file content, that is easily done this way
#include <stdio.h>
#include <stdlib.h>
char *readFileContent(const char *const filename)
{
size_t size;
FILE *file;
char *data;
file = fopen(filename, "r");
if (file == NULL)
{
perror("fopen()\n");
return NULL;
}
/* get the file size by seeking to the end and getting the position */
fseek(file, 0L, SEEK_END);
size = ftell(file);
/* reset the file position to the begining. */
rewind(file);
/* allocate space to hold the file content */
data = malloc(1 + size);
if (data == NULL)
{
perror("malloc()\n");
fclose(file);
return NULL;
}
/* nul terminate the content to make it a valid string */
data[size] = '\0';
/* attempt to read all the data */
if (fread(data, 1, size, file) != size)
{
perror("fread()\n");
free(data);
fclose(file);
return NULL;
}
fclose(file);
return data;
}
int main()
{
char *content;
content = readFileContent(inputFilename);
if (content != NULL)
{
printf("%s\n", content);
free(content);
}
reutrn 0;
}
and this will of course fail in the rare case where the file size exceeds the available RAM, but it will not cause undedined behavior, because that case is handeled as a malloc() failure.

Related

Reading the files contents to the allocated string

I am trying to read the contents of a file and copy those contents into a string which has dynamic memory. However my program keeps allocating only 8 bytes to x. Ultimately I'm trying to create a general function that can read contents from a file and then return the contents as a char. Any help is appreciated.
char* readFile(unsigned long size, char *fileName) {
FILE *file = fopen(fileName, "r");
int c;
if(file != NULL)
{
while(c != EOF){ //calculate size of file
c = fgetc(file); //store character
size++;
}
char *x = (char *)malloc((size) * (sizeof(char))); // Size of x = 8 and I'm not sure why
rewind(file);
printf("\n");
int i = 0;
while(size - 1 > i){ //Reading the files contents to the allocated string
c = fgetc(file); //store character
if(c == EOF){
break;
}
x[i] = c;
i++;
}
fclose(file);
printf("Done Reading");
}
else
{
printf("\nError: Unable to open the file for Reading.\n");
}
rewind(file);
return 0;
}
I get a segmentation fault when I run
char* str = readFile(size, originalFile);
I would use stat to first get the size of your file
stat() retrieves information about the file pointed
to by pathname;
And then I made some tiny modifications to your function to make it work:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
char* readFile(char *fileName) {
FILE *file;
struct stat st;
if (!(file = fopen(fileName, "r")))
return NULL;
stat(fileName, &st);
unsigned long size = st.st_size;
char *x;
if (!(x = (char *)malloc((size + 1) * (sizeof(char))))) // Size of x = 8 and I'm not sure why
return NULL;
unsigned long i = 0;
while (i < size) //Reading the files contents to the allocated string
x[i++] = getc(file);
x[i] = '\0';
fclose(file);
printf("Done Reading\n");
return x;
}
int main(void) {
char *fileName = "a.txt";
char *res = readFile(fileName);
printf("%s\n", res);
return 0;
}
Don't forget that in C strings are NULL terminated, you need to malloc size+1 to add the final '\0'.
This is (IMHO) an easier way to find the size of the file:
char *readFile(const char *fileName)
{
unsigned long size = 0;
char *x;
FILE *file = fopen(fileName, "r");
int c;
if (file != NULL)
{
fseek(file, 0, SEEK_END); /* SET the position at EOF */
size = ftell(file); /* Record the position at EOF to return size of file */
rewind(file); /* SET position back to Origin */
printf("size detected %ld\n", size); // reads correct size
x = (char *)malloc((size) * (sizeof(char)));
rewind(file);
printf("\n");
int i = 0;
while (size - 1 > i)
{ //Reading the files contents to the allocated string
c = fgetc(file); //store character
if (c == EOF)
{
break;
}
x[i] = c;
i++;
}
fclose(file);
printf("Done Reading\n");
}
else
{
printf("\nError: Unable to open the file for Reading.\n");
return NULL;
}
rewind(file);
return x; // * you need to return x not zero
}
Successfully reads the content of the file:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *data;
data = readFile("records.txt");
printf("%s\n", data);
return 0;
}

Char* parse error from char array

I read a file and stock all characters like this:
void ReadFile()
{
int c;
FILE *file;
int string_size;
file = fopen("/userFiles/ex.txt", "r");
char * content;
if (file)
{
// Seek the last byte of the file
fseek(file, 0, SEEK_END);
// Offset from the first to the last byte, or in other words, filesize
string_size = ftell(file);
// go back to the start of the file
rewind(file);
// Allocate a string that can hold it all
content = malloc((string_size + 1) * sizeof(char));
int i = 0;
while ((c = getc(file)) != EOF)
{
//printf("%c",(char) c);
content[i] = (char) c;
i++;
}
content[string_size] = '\0';
printf("content: %s",content);
fclose(file);
}
else
{
printf("not load\n");
}
}
Problem is if i read each carachter i've got the content of the file but if i do:
printf("content: %s",content);
I got just a symbol and not text whereas i need to pass the content var with correct text in argument of a json reply.
This is the first line of the file (CRC32):
�ex.txt k��X� ?xml version="1.0" encoding="utf-8"?
I compiled and ran the following code and it shows no major problem when executed.
The compilable version I used is (cmdline: gcc main.c -Wall -Wextra -o main):
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
int c;
FILE *file;
int string_size;
file = fopen("plop", "r");
char * content;
if (file == NULL)
{
perror("fprintf");
return 1;
}
// Seek the last byte of the file
fseek(file, 0, SEEK_END);
// Offset from the first to the last byte, or in other words, filesize
string_size = ftell(file);
// go back to the start of the file
rewind(file);
// Allocate a string that can hold it all
content = malloc((string_size + 1) * sizeof(char));
int i = 0;
while ((c = getc(file)) != EOF)
{
//printf("%c",(char) c);
content[i] = (char) c;
i++;
}
content[string_size] = '\0';
printf("content: %s", content);
return 0;
}
Maybe your file has a binary content?
What is the symbol printed, that you mentioned?
I think you should use quotes "" around the content string:
printf("content: \"%s\"",content);

Generating array of word pointers in c

I have a problem where I have to read a text file made of 264064 words into a buffer and then create an array of word-pointers in a separate array. I am not sure how to go about creating the array of word-pointers which points to different amount of characters in the buffer. Any hints on how to approach this problem?
#include <stdlib.h>
#include <string.h>
int main()
{
int i,wordCount=0;
long bufsize;
char ch;
//Open File and get number of lines in file
FILE *fp = fopen("words2.txt", "r");
if (fp == NULL) {
printf("Error!");
exit(1);
}
do {
ch = fgetc(fp);
if (ch == '\n')
{
wordCount++;
}
} while (ch != EOF);
fclose(fp);
printf("%d\n",wordCount);
//Reading Words into buffer rawtext
char *rawtext;
fp = fopen("words2.txt", "rb");
if (fp != NULL)
{
if (fseek(fp, 0L, SEEK_END) == 0) {
bufsize = ftell(fp);
if (bufsize == -1) {
exit(1);
}
rawtext = malloc(sizeof(char) * (bufsize + 1));
if (fseek(fp, 0L, SEEK_SET) != 0) { exit(1); }
size_t newLen = fread(rawtext, sizeof(char), bufsize, fp);
if (ferror(fp) != 0) {
fputs("Error reading file", stderr);
} else {
rawtext[newLen++] = '\0';
}
}
//Print out buffer
printf("%s",rawtext);
fclose(fp);
free(rawtext);//Free allocated memory
char *ptr[wordCount];//Array for word-pointers
}
}
If you keep your rawtext (i.e. do not free it), you could use strchr('\n') to go through the content, store to the array the current position, detect every new line char, terminate the string at this new line character, and go ahead. Thereby, your ptr-array will point to each word inside rawtext at the end (that's why you should not free rawtext then, because the pointers would then point to invalid memory):
The following code should work:
char* currWord = rawtext;
int nrOfWords = 0;
char* newlinePos;
while ((newlinePos = strchr(currWord,'\n')) != NULL) {
*newlinePos = '\0';
ptr[nrOfWords++] = currWord;
currWord = newlinePos + 1;
}
if (*currWord) {
ptr[nrOfWords++] = currWord;
}
Side note: expression char *ptr[wordCount] might put your pointer array on the stack, which has limited space, at least less than the heap. This could get a problem if your file contains a lot of words. Use char *ptr = malloc((wordCount+1) * sizeof(char*)) to reserve memory on the heap. Note also the +1 after wordCount for the case that the last word is not terminated by a new line.

How to make a char array from a file?

#include <stdio.h>
#include <stdlib.h>
int count_arr(FILE *file)
{
int c,count=0;
//FILE *file;
//file = fopen("test.txt", "r");
if (file) {
while ((c = getc(file)) != EOF){
putchar(c);
++count;}
fclose(file);
}
return count;
}
void make_arr (FILE *file, char arr[]){
int c,n=0,count=0;
char ch;
//FILE *file;
//file = fopen("test.txt", "r");
if (file) {
while ((c = getc(file)) != EOF){
ch = (char)c;
arr[n]=ch;
++n; }
fclose(file);
}
}
int main(){
FILE *file;
int n;
//scanf("%c",&file_name);
file = fopen("test.txt","r");
int count = count_arr(file);
char arr [count];
make_arr(file, arr);
for(n=0; n<count;++n) printf("%c",arr[n]);
}
So far this is all I have for my code. I know I am doing it completely wrong. When I print out the char array it prints random junk... I am trying to code a function "make_arr" that passes an array which gets stored with characters from a file. Any help would be appreciated!
Here is an small example that reads a file into a buffer:
FILE* file = fopen("file.txt", "r");
// get filesize
fseek(file, 0, SEEK_END);
int fsize = ftell(file);
fseek(file, 0, SEEK_SET);
// allocate buffer **note** that if you like
// to use the buffer as a c-string then you must also
// allocate space for the terminating null character
char* buffer = malloc(fsize);
// read the file into buffer
fread(buffer, fsize, 1, file);
// close the file
fclose(file);
// output data here
for(int i = 0; i < fsize; i++) {
printf("%c", buffer[i]);
}
// free your buffer
free(buffer);
If you really would like to use a function to fill your buffer this would work (not really see the point though), although I still will make only one read operation:
void make_array(FILE* file, char* array, int size) {
// read entire file into array
fread(array, size, 1, file);
}
int main(int argc,char** argv) {
// open file and get file size by first
// moving the filepointer to the end of the file
// and then using ftell() to tell its position ie the filesize
// then move the filepointer back to the beginning of the file
FILE* file = fopen("test.txt", "r");
fseek(file, 0, SEEK_END);
int fs = ftell(file);
fseek(file, 0, SEEK_SET);
char array[fs];
// fill array with content from file
make_array(file, array, fs);
// close file handle
fclose(file);
// output contents of array
for(int i = 0; i < fs; i++) {
printf("%c\n", array[i]);
}
return 0;
}
Like I stated in the comments above you need to add space for the terminating null character if you like to use the char array as a string:
char* array = malloc(fs + 1);
fread(array, fs, 1, file);
// add terminating null character
array[fs] = '\0';
// print the string
printf("%s\n", array);

How to read the content of a file to a string in C?

What is the simplest way (least error-prone, least lines of code, however you want to interpret it) to open a file in C and read its contents into a string (char*, char[], whatever)?
I tend to just load the entire buffer as a raw memory chunk into memory and do the parsing on my own. That way I have best control over what the standard lib does on multiple platforms.
This is a stub I use for this. you may also want to check the error-codes for fseek, ftell and fread. (omitted for clarity).
char * buffer = 0;
long length;
FILE * f = fopen (filename, "rb");
if (f)
{
fseek (f, 0, SEEK_END);
length = ftell (f);
fseek (f, 0, SEEK_SET);
buffer = malloc (length);
if (buffer)
{
fread (buffer, 1, length, f);
}
fclose (f);
}
if (buffer)
{
// start to process your data / extract strings here...
}
Another, unfortunately highly OS-dependent, solution is memory mapping the file. The benefits generally include performance of the read, and reduced memory use as the applications view and operating systems file cache can actually share the physical memory.
POSIX code would look like this:
int fd = open("filename", O_RDONLY);
int len = lseek(fd, 0, SEEK_END);
void *data = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0);
Windows on the other hand is little more tricky, and unfortunately I don't have a compiler in front of me to test, but the functionality is provided by CreateFileMapping() and MapViewOfFile().
If "read its contents into a string" means that the file does not contain characters with code 0, you can also use getdelim() function, that either accepts a block of memory and reallocates it if necessary, or just allocates the entire buffer for you, and reads the file into it until it encounters a specified delimiter or end of file. Just pass '\0' as the delimiter to read the entire file.
This function is available in the GNU C Library, http://www.gnu.org/software/libc/manual/html_mono/libc.html#index-getdelim-994
The sample code might look as simple as
char* buffer = NULL;
size_t len;
ssize_t bytes_read = getdelim( &buffer, &len, '\0', fp);
if ( bytes_read != -1) {
/* Success, now the entire file is in the buffer */
If you are reading special files like stdin or a pipe, you are not going to be able to use fstat to get the file size beforehand. Also, if you are reading a binary file fgets is going to lose the string size information because of embedded '\0' characters. Best way to read a file then is to use read and realloc:
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int main () {
char buf[4096];
ssize_t n;
char *str = NULL;
size_t len = 0;
while (n = read(STDIN_FILENO, buf, sizeof buf)) {
if (n < 0) {
if (errno == EAGAIN)
continue;
perror("read");
break;
}
str = realloc(str, len + n + 1);
memcpy(str + len, buf, n);
len += n;
str[len] = '\0';
}
printf("%.*s\n", len, str);
return 0;
}
Note: This is a modification of the accepted answer above.
Here's a way to do it, complete with error checking.
I've added a size checker to quit when file was bigger than 1 GiB. I did this because the program puts the whole file into a string which may use too much ram and crash a computer. However, if you don't care about that you could just remove it from the code.
#include <stdio.h>
#include <stdlib.h>
#define FILE_OK 0
#define FILE_NOT_EXIST 1
#define FILE_TOO_LARGE 2
#define FILE_READ_ERROR 3
char * c_read_file(const char * f_name, int * err, size_t * f_size) {
char * buffer;
size_t length;
FILE * f = fopen(f_name, "rb");
size_t read_length;
if (f) {
fseek(f, 0, SEEK_END);
length = ftell(f);
fseek(f, 0, SEEK_SET);
// 1 GiB; best not to load a whole large file in one string
if (length > 1073741824) {
*err = FILE_TOO_LARGE;
return NULL;
}
buffer = (char *)malloc(length + 1);
if (length) {
read_length = fread(buffer, 1, length, f);
if (length != read_length) {
free(buffer);
*err = FILE_READ_ERROR;
return NULL;
}
}
fclose(f);
*err = FILE_OK;
buffer[length] = '\0';
*f_size = length;
}
else {
*err = FILE_NOT_EXIST;
return NULL;
}
return buffer;
}
And to check for errors:
int err;
size_t f_size;
char * f_data;
f_data = c_read_file("test.txt", &err, &f_size);
if (err) {
// process error
}
else {
// process data
free(f_data);
}
What is the simplest way (least error-prone, least lines of code, however you want to interpret it) to open a file in C and read its contents into a string ...?
Sadly, even after years, answers are error prone and many lack proper string formation and error checking.
#include <stdio.h>
#include <stdlib.h>
// Read the file into allocated memory.
// Return NULL on error.
char* readfile(FILE *f) {
// f invalid? fseek() fail?
if (f == NULL || fseek(f, 0, SEEK_END)) {
return NULL;
}
long length = ftell(f);
rewind(f);
// Did ftell() fail? Is the length too long?
if (length == -1 || (unsigned long) length >= SIZE_MAX) {
return NULL;
}
// Convert from long to size_t
size_t ulength = (size_t) length;
char *buffer = malloc(ulength + 1);
// Allocation failed? Read incomplete?
if (buffer == NULL || fread(buffer, 1, ulength, f) != ulength) {
free(buffer);
return NULL;
}
buffer[ulength] = '\0'; // Now buffer points to a string
return buffer;
}
Note that if the text file contains null characters, the allocated data will contain all the file data, yet the string will appear to be short. Better code would also return the length information so the caller can handle that.
char* readfile(FILE *f, size_t *ulength_ptr) {
...
if (ulength_ptr) *ulength_ptr == *ulength;
...
}
If the file is text, and you want to get the text line by line, the easiest way is to use fgets().
char buffer[100];
FILE *fp = fopen("filename", "r"); // do not use "rb"
while (fgets(buffer, sizeof(buffer), fp)) {
... do something
}
fclose(fp);
If you're using glib, then you can use g_file_get_contents;
gchar *contents;
GError *err = NULL;
g_file_get_contents ("foo.txt", &contents, NULL, &err);
g_assert ((contents == NULL && err != NULL) || (contents != NULL && err == NULL));
if (err != NULL)
{
// Report error to user, and free error
g_assert (contents == NULL);
fprintf (stderr, "Unable to read file: %s\n", err->message);
g_error_free (err);
}
else
{
// Use file contents
g_assert (contents != NULL);
}
}
Just modified from the accepted answer above.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
char *readFile(char *filename) {
FILE *f = fopen(filename, "rt");
assert(f);
fseek(f, 0, SEEK_END);
long length = ftell(f);
fseek(f, 0, SEEK_SET);
char *buffer = (char *) malloc(length + 1);
buffer[length] = '\0';
fread(buffer, 1, length, f);
fclose(f);
return buffer;
}
int main() {
char *content = readFile("../hello.txt");
printf("%s", content);
}
// Assumes the file exists and will seg. fault otherwise.
const GLchar *load_shader_source(char *filename) {
FILE *file = fopen(filename, "r"); // open
fseek(file, 0L, SEEK_END); // find the end
size_t size = ftell(file); // get the size in bytes
GLchar *shaderSource = calloc(1, size); // allocate enough bytes
rewind(file); // go back to file beginning
fread(shaderSource, size, sizeof(char), file); // read each char into ourblock
fclose(file); // close the stream
return shaderSource;
}
This is a pretty crude solution because nothing is checked against null.
I will add my own version, based on the answers here, just for reference. My code takes into consideration sizeof(char) and adds a few comments to it.
// Open the file in read mode.
FILE *file = fopen(file_name, "r");
// Check if there was an error.
if (file == NULL) {
fprintf(stderr, "Error: Can't open file '%s'.", file_name);
exit(EXIT_FAILURE);
}
// Get the file length
fseek(file, 0, SEEK_END);
long length = ftell(file);
fseek(file, 0, SEEK_SET);
// Create the string for the file contents.
char *buffer = malloc(sizeof(char) * (length + 1));
buffer[length] = '\0';
// Set the contents of the string.
fread(buffer, sizeof(char), length, file);
// Close the file.
fclose(file);
// Do something with the data.
// ...
// Free the allocated string space.
free(buffer);
easy and neat(assuming contents in the file are less than 10000):
void read_whole_file(char fileName[1000], char buffer[10000])
{
FILE * file = fopen(fileName, "r");
if(file == NULL)
{
puts("File not found");
exit(1);
}
char c;
int idx=0;
while (fscanf(file , "%c" ,&c) == 1)
{
buffer[idx] = c;
idx++;
}
buffer[idx] = 0;
}

Resources