You are here:

C++/Writing to file using C over Linux

Advertisement


Question
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
<?
$data=array(
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
)
?>
//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

  FILE *fp1;
  fp1 = fopen("/var/www/html/data1.php", "w");
  fprintf (fp1, "<?\n");
  fprintf (fp1, "$data=array(\n");
  fclose(fp1);

//the loop of updating the array
//
//some code here
//
//FILE *fp1;
//fp1 = fopen("/var/www/html/data1.php", "a");
//fprintf (fp1, "%f,\n", KBpsr);
//fclose(fp1);  
//
//end of the loop

  FILE *fp2;
  fp2 = fopen("/var/www/html/data1.php", "a");
  fprintf (fp2, ")\n");
  fprintf (fp2, "?>\n");
  fclose(fp2);

Thank you in advance.  

Answer
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:

   rewind(fp1);

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:

50,
,

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:

1,

}

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):

[<][?][\n][$][d][a][t][a][=][a][r][r][a][y][(][\n][1][,][\n][2][,][\n][3][,][\n][4][,][\n][5][,][\n][6][,][\n][7][,][\n][8][,][\n][9][,][\n][1][0][,][\n][)][\n][?][>][\n]

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.

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.