Reading content from a file and storing it to String in C - c

I've written a simple http server in C and am now trying to implement HTML files.
For this I need send a response, containing the content of the HTML file.
How do I do that best?
Do I read the file line by line, and if so how do I store them in a single string?
Thanks already!

Here is an example of reading a text file by chunks which, if the file is big, would be faster than reading the file line by line.
As #tadman said in his comment, text files aren't generally big so reading them in chunks doesn't make any real difference in speed but web servers serve other files too - like perhaps photos or movies (which are big). So if you are only going to read text files then reading line by line might be simpler (you could use fgets instead of fread) but if you are going to read other kinds of files then reading all of them in chunks means you can do it the same way for all of them.
However, as #chux said in his comment, there is another difference between reading text files and binary files. The difference is that text files are opened in text mode: fopen(filename,"r"); and binary files must be opened in binary mode: fopen(filename,"rb"); A web server could probably open all files in binary mode because web browsers ignore whitespace anyway but other kinds of programs need to know what the line endings will be so it can make a difference.
https://onlinegdb.com/HkM---r2X
#include <stdio.h>
int main()
{
// we will make the buffer 200 bytes in size
// this is big enough for the whole file
// in reality you would probably stat the file
// to find it's size and then malloc the memory
// or you could read the file twice:
// - first time counting the bytes
// - second time reading the bytes
char buffer[200]="", *current=buffer;
// we will read 20 bytes at a time to show that the loop works
// in reality you would pick something approaching the page size
// perhaps 4096? Benchmarking might help choose a good size
int bytes, chunk=20, size=sizeof(buffer)/sizeof(char);
// open the text file in text mode
// if it was a binary file you would need "rb" instead of "r"
FILE *file=fopen("test.html","r");
if(file)
{
// loop through reading the bytes
do {
bytes=fread(current,sizeof(char),chunk,file);
current+=bytes;
} while (bytes==chunk);
// close the file
fclose(file);
// terminate the buffer so that string function will work
*current='\0';
// print the buffer
printf("%s",buffer);
}
return 0;
}

Related

How to write at the middle of a file in c

Is it possible to write at the middle of a file for example I want to insert some string at the 5th position in the 2nd line of a file in c ?
I'm not very familiar with some of C functions that are related to handling files , if someone could help me I would appreciate it
I tried using fputs but I couldn't insert characters at the desired location
open a new output file
read the input file line by line (fgets) writing each line out to a new file as you read.
When you hit the place you want to insert write the new line(s)
The carry on copy the old lines to the new file
close input and output
rename output file to input
Continuing from my comments above. Here's what I'd do:
Create two large, static char[] buffers of the same size--each large enough to store the largest file you could possibly ever need to read in (ex: 10 MiB). Ex:
#define MAX_FILE_SIZE_10_MIB (10*1024*1024)
static char buffer_file_in[MAX_FILE_SIZE_10_MIB];
static char buffer_file_out[MAX_FILE_SIZE_10_MIB];
Use fopen(filename, "r+") to open the file as read/update. See: https://cplusplus.com/reference/cstdio/fopen/. Read the chars one-by-one using fgetc() (see my file_load() function for how to use fgetc()) into the first large char buffer you created, buffer_file_in. Continue until you've read the whole file into that buffer.
Find the location of the place you'd like to do the insertion. Note: you could do this live as you read the file into buffer_file_in the first time by counting newline chars ('\n') to see what line you are on. Copy chars from buffer_file_in to buffer_file_out up to that point. Now, write your new contents into buffer_file_out at that point. Then, finish copying the rest of buffer_file_in into buffer_file_out after your inserted chars.
Seek to the beginning of the file with fseek(file_pointer, 0, SEEK_SET);
Write the buffer_file_out buffer contents into the file with fwrite().
Close the file with fclose().
There are some optimizations you could do here, such as storing the index where you want to begin your insertion, and not copying the chars up to that point into buffer_file_in, but rather, simply copying the remaining of the file after that into buffer_file_in, and then seeking to that point later and writing only your new contents plus the rest of the file. This avoids unnecessarily rewriting the very beginning of the fie prior to the insertion point is all.
(Probably preferred) you could also just copy the file and the changes you insert straight into buffer_file_out in one shot, then write that back to the file starting at the beginning of the file. This would be very similar to #pm100's approach, except using 1 file + 1 buffer rather than 2 files.
Look for other optimizations and reductions of redundancy as applicable.
My approach above uses 1 file and 1 or 2 buffers in RAM, depending on implementation. #pm100's approach uses 2 files and 0 buffers in RAM (very similar to what my 1 file and 1 buffer approach would look like), depending on implementation. Both approaches are valid.

Reading a string from a file with C. Fopen with w+ mode is not working

I made a C program that reads a string from a .txt file, then it encrypts the string, and finally it writes the string in the same file.
The thing is that if I use fopen("D:\\Prueba.txt","w+"), the program doesn't work, it prints garbage like this )PHI N.
I've debugged and I know the error is there in that line, because if I use fopen("D:\\Prueba.txt","r+"), the program works, and it writes what it should.
But I want to use w+ because it will rewrite what the .txt file had. Why is w+ not working?
If you're opening with w+ to first read the content, that's not going to work. From C11:
w+: truncate to zero length or create text file for update.
What's probably happening is that you read data from the now empty file but don't correctly check that it worked. That would explain the weird "content" you see of )PHI N.
One solution is to open the file as with r, open another file with w, and transfer the contents, encrypting them as part of that process. Then close both, delete the original, and rename the new one to the original name. This will allow you to process arbitrarily-sized files since you process them a bit at a time.
If you don't want to use a temporary file, and you're sure you can store the entire content in memory, you could open it r+, get the content, the reopen it with a new mode, such as with:
FILE *readFh = fopen( "myfile.txt", "r+");
// Read in content, massage as needed.
FILE *writeFh = frepoen( NULL, "w+", readFh);
// Provided that worked, you should now have an empty file to write to.
// Write back your massaged data.

How can C read content that is newly inserted into a file?

I want to first write something to a file, then use fgets to read it. But I want it to work without close it and switch file open mode between read and write,
I have tried r+ and w+ for file open. For r+ it is able to read original content but fail to read newly inserted content. For w+ it does not read anything I think that's because w+ clear the original content.
I currently found no way to read the newly inserted content of a file before close and switch file open mode, although with fflush new content is already written to a file and can be viewed externally.
Here is a simple code snippet for testing.
#include <stdio.h>
int main()
{
FILE *fp = NULL;
char line[256];
int status;
/*input by user*/
scanf("%s", line);
/*write to a file*/
fp = fopen("f5.txt", "w+");
fprintf(fp, "%s", line);
fflush(fp); /*flush buffer*/
/*read it*/
char lineRead[256];
while (fgets(lineRead, 5, fp) != NULL) {
puts(lineRead);
}
fclose(fp);
}
You might use not only fflush, but also rewind, fseek, ftell (or even fgetpos & fsetpos)
Beware that any standard IO function can fail, and you should check that.
On Linux, some files (e.g. fifo(7)) are not seekable.
Perhaps you want some higher level way of storing persistent data on the disk. Did you consider using some library for indexed files (like gdbm) or for databases (like sqlite)? Or even use a full fledged database, like with some RDBMS (e.g. PostGreSQL or MySQL or MariaDB which are free software), or some NoSQL thing like e.g. MongoDB ?
There is no way to insert a sequence of bytes in the middle of some file or to delete, i.e. remove, a sequence of bytes inside a file. This is a fundamental limitation of file systems on most current operating systems (and on all usual ones like Linux & Windows & Android & MacOSX). You generally should copy that file (by chunks) into some other one (and libraries like gdbm or sqlite don't do that, they either append some data to a file at its end or rewrite some bytes inside the file; they might also truncate a file).
In particular, if you want to programmatically insert some line in the middle of some small text file, you usually should read the file entirely in some appropriate data structure, modify that data structure in memory, then dump that data structure into the (overwritten) file.
You need to use fseek() to return to the beginning of the file before trying to read it.

Inserting text in a file instead of overwriting in c

How can I insert characters in a file using C instead of overwriting? I also want to write in start of file and end of a file. I tried this method but it didn't work out (I can re-position but I cannot insert. The text is overwritten)
I've tried this, but it didn't work:
fword = fopen("wrote.txt", "rb+");
fseek(fword, 0, SEEK_SET);
fscanf(fword, "%c", &l);
To add text at the end, you can open the file with "a" mode (check the fopen manual). It will write your text to end.
To add text in other positions, you have to read everything after that to memory, write what you want and then write the rest.
Files are abstractions of byte streams, there is no such concept as insert in a byte stream, you can seek into certain place and write data there. The bytes you wrote will lay in the file as an array of bytes, if the writing exceeds the current file size, the file will be extended.

Prepend text to a file in C

I want to add a standard header to a file (or group of files) using C. These files could be quite large, so it would be a bad idea to load them into memory, or copy them into temporary files (I think).
Is there a way to simply prepend the header directly to each file?
The header itself is quite small, not more than 1 KB
You cannot insert data into a file.
However, there is no need to load the entire file in memory. Just create a new file, write the data you are inserting, then copy the contents of the original file to the new file (do it block by block instead of loading the entire file into memory).
Finally, delete the original file and rename the new file to match the original file.
This is the most efficient way to do this and it is reasonably efficient.
It should be possible without a temporary file - you can read the file from the end, block by block, writing each block back at (original_position + header_size). The first block would be written back at header_size, leaving room for the header.
However, you don't really want to do this. It would corrupt the file if aborted (think: out of disk space, other I/O error, power down, whatever).
Thus, you should actually use temporary file - write to it everything you need, then rename it to the original file's name (assuming you create temporary file on the same file system, otherwise you'd need to copy).
Edit: to clarify what I mean, simplified solution when the whole file fits in RAM:
allocate buffer same size as the file
open the file, and read it into the buffer
seek(file, header_size) and write the buffer here
seek(file, 0) write the header
If the file is to big, you can allocate smaller buffer and repeat reads/writes starting with read at file_size - buffer_size and write at file_size - buffer_size + header_size. Then repeat with next chunk read at file_size - 2 * buffer_size, write at file_size - 2 * buffer_size + header_size, and so on.
But let me repeat: you risk corrupting your file if it fails!

Resources