C++/Writing to file using C over Linux
Hello Mr. McArdell
I am working on Linux Fedora core 3 with gcc compiler, I want to write to a file in the following order
//Beginning of the file
//End of the file
This values of the array will be updated every 5 seconds... so I opened the file at the first in write mode, then I made a loop for updating the values of the array in appende mode and then go to the beginning of the program and so on... my problem is when I get to the beginning of the file its opened in the write mode and all the rest of the file lines is deleted and over written (I want the following: when I write at the first line of the file, I want to keep the rest of the lines as they are until they are updated by the loop of the program and so on) I am using fprintf to write to the file
//first open the file in write mode
fp1 = fopen("/var/www/html/data1.php", "w");
fprintf (fp1, "<?\n");
fprintf (fp1, "$data=array(\n");
//the loop of updating the array
//some code here
//fp1 = fopen("/var/www/html/data1.php", "a");
//fprintf (fp1, "%f,\n", KBpsr);
//end of the loop
fp2 = fopen("/var/www/html/data1.php", "a");
fprintf (fp2, ")\n");
fprintf (fp2, "?>\n");
Thank you in advance.
I am sorry but you might have noticed that I am an expert in the C++ section not the C section. This means that I no longer write pure C code, so I probably cannot give as good an answer as an expert who writes just C.
In your case you have several problems.
First you open the file to start with in write and truncate mode. This will truncate (i.e. delete) any previous contents of the file each time you open it. To prevent truncating the file always open the file using ‘a’. However, this leaves the file write location positioned at the end of the file so you have to rewind to the start of the file. You can make a call to:
Or use fseek:
fseek( fp1, 0L, SEEK_SET );
The second problem is that line based text files tend to have lines of different lengths. Overwriting one line with a line of a different length will leave your file in a rubbish state for example:
Overwriting the line 5, in your question example with 50, will have the following effect:
This occurs because the 0 replaces the comma, the comma replaces the new line character and the new line character replaces the 6 on the following line.
Overwriting the line 10, with the value 1, would have the following effect:
That is you get an additional new line. This occurs as the comma after the 1 replaces the 0 and the new line after the comma replaces the comma. The original new line is still in place. Hence you end up with two new lines.
The reason this happens is that although a text file might be arranged when displayed as a two dimensional entity of lines of characters, really all files are stored as a single dimensional sequences of bits, generally arranged as sequences of 8-bit bytes. So your file contains the bytes for the sequences of characters shown below. I have shown each byte as the character surrounded by[ and ] to show their boundaries, with new line represented as the C/C++ new line escape character sequence \n. Of course this is a long sequence so is wrapped over several lines (two and a half in my editor):
If you wish to view your text file as raw data then try opening it in a hex editor, of which there are many for Linux, including ones provided with GUIs such as GNOME).
The third point is that data written to a file is buffered, at least by the C library, and also probably by the operating system. This means that even if you have written to the file it may well not have been written to disk yet. The buffers are flushed when the file is closed, and can also be flushed explicitly by calling fflush(fp1). They are also flushed automatically when they fill up.
So unless a long time elapses between the opening of the file, the writing of the data and the closing of the file I would not worry about not disturbing the data in the file. It is probable that your program has finished producing the data before it could physically be written to disk anyway – remember writing to disk is orders of magnitude slower than writing to memory, and you have to write a complete file system block of data to a file even if you only have a few bytes to write.
I am still not sure what your exact motivation is for not wanting to change the array data in your file until it is explicitly written over. I am also uncertain if you re-run the program from scratch every 5 seconds or whether you run the program continuously, but just perform the file update every 5 seconds.
So my advice is:
a) If you always generate a complete new set of data and this is done quickly then do not bother with trying to not modify the data until it is ready to be updated. Open the file using ‘w’, generate and write the data, close the file. If the file is not much longer than that shown in your question it will most likely only get written to disk once you call fclose anyway.
b) If you always generate a complete new set of data but each value is generated very slowly then collect all the data first, then write it all out in one go: open, write all data, close.
c) If you only update some values at a time then the part of the file that contains data that can change must comprise fixed length records. You could do this for example by specifying a minimum width of the data written out in your fprintf field specifications. For example if the maximum value to be written out is 9999999.999 (millions, with three decimal places) then a minimum field width of 11 would be appropriate:
fprintf (fp1, "%11.3f,\n", KBpsr);
I may have misremembered the exact details of specifying minimum field width and decimal places using fprintf – remember I am a C++ expert and do not write much pure C these days, and I/O is one area where C and C++ differ.
d) If the resultant file is to be used by another process and this process may try to access it while it is being updated then I suggest you look into Linux file locking mechanisms. See http://en.wikipedia.org/wiki/File_locking
for an introduction to the subject.
e) Use the Linux man pages to check the small print of the functions you are using. Use the Internet and Internet search engines to find more general information on related topics – such as file locking for example.