Solved

fwrite problem

Posted on 2004-03-31
24
837 Views
Last Modified: 2008-02-26
Hi,

I got this problem...I use fwrite to write some structs into my files and sometimes it works perfectly but sometimes it didn't.
Here are my codes..

typedef struct _AStruct
{
      DataA myFiles[100];
      int SilbingIndex[100];
      int OtherIndex[60];
} AStruct;

typdef struct _DataA
{
    int index;
    UCHAR  Name[Name_Len];
    DataB   DataBuf[100];
} DataA

typdef struct _DataB
{
   char   DataBuffer[100];
   char   DataBuffer2[100];
} DataB


int  WriteFiles()
{
      int ret;
      DataFile = fopen(lpCurrentDataFilePath, "wb");

      EnterCriticalSection(lpcs_CNum);
      ret = fwrite(&ATree.myFiles, sizeof(DataA), 100, DataFile); <-- correct me if I'm wrong...it will return 100 if fwrite works fine, right?  but sometimes, it will return 99.  And I use "GetLastError", and it return 0...

      ret = fwrite(&ATree.SilbingIndex, sizeof(int), 100, DataFile);
                ret = fwrite(&ATree.OtherIndex, sizeof(int), 60, DataFile);
      ret = fclose(CSFile);  <-- this will return -1 if the first fwrite returns 99.

      return ret;
}

What's wrong with my codes?  Sometimes it works fine but sometimes it doesn't.  What should I do??
0
Comment
Question by:xenia27
  • 8
  • 5
  • 5
  • +2
24 Comments
 
LVL 30

Expert Comment

by:Axter
ID: 10729945
ret = fwrite(&ATree.myFiles, sizeof(DataA), 100, DataFile);

This line has the wrong sizeof variable.
0
 
LVL 30

Expert Comment

by:Axter
ID: 10729947
Try this instead:
ret = fwrite(&ATree.myFiles, 1, sizeof(ATree.myFiles), DataFile);
0
 
LVL 30

Expert Comment

by:Axter
ID: 10729962
fwrite has the following parameters:
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );

Parameters
buffer
Pointer to data to be written

size
Item size in bytes

count
Maximum number of items to be written

stream
Pointer to FILE structure

So really your function should read like this:
ret = fwrite(&ATree.myFiles, sizeof(ATree.myFiles), 1, DataFile);

However, it will work both ways.  I myself always use 1 for one of the parameters, and then use the other parameter for the total size of the buffer.
0
 
LVL 30

Expert Comment

by:Axter
ID: 10729966
>>ret = fclose(CSFile);  <-- this will return -1 if the first fwrite returns 99.

Using CSFile will give you an error since it's not the variable used to open the file.

Should be Datafile

ret = fclose(Datafile);  
0
 
LVL 30

Assisted Solution

by:Axter
Axter earned 100 total points
ID: 10729974
FYI:
ret = fwrite(&ATree.SilbingIndex, sizeof(int), 100, DataFile);

A safer way to write the above code would be the folowing:

ret = fwrite(&ATree.SilbingIndex,
                     sizeof(ATree.SilbingIndex[0]),
                     sizeof(ATree.SilbingIndex)/sizeof(ATree.SilbingIndex[0]),
                     DataFile);

Looks bulky, but the advantage of this is that if you change the type for variable ATree.SilbingIndex, or if you change the array size, this code will still be valid.

With the original code, you would have to change the fwrite code every time you change the size of the array, or you change the variable type.
You also have to worry about making a typo or entering the wrong number.
By using sizeof() you're letting the compiler do the work for you.
0
 

Author Comment

by:xenia27
ID: 10730044
Can I write this??

ret = fwrite(&ATree, sizeof(AStrue), 1, DataFile);
ATree is a poitner.

will this work?
0
 

Author Comment

by:xenia27
ID: 10730053
Another question, I use "fwrite(&ATree, sizeof(AStruct), 1, DataFile)", and why there is some information missed???
0
 
LVL 12

Expert Comment

by:stefan73
ID: 10730061
Hi Axter,
> By using sizeof() you're letting the compiler do the work for you.
Exactly - when fwrite returns only a partial write of the array (say, 99 of 100 elements), it's an error condition anyway. So write the entire array as one chunk. Or even better, write the whole ATree as a single piece. It's faster, it's more obvious what you're doing in the code, and it's less error-prone.

Cheers,
Stefan
0
 
LVL 12

Expert Comment

by:stefan73
ID: 10730067
xenia27,
> Another question, I use "fwrite(&ATree, sizeof(AStruct), 1, DataFile)",
> and why there is some information missed???

Which information is missed? It should be fine. But better write
fwrite(&ATree, sizeof(ATree), 1, DataFile)

That makes is more obvious that you're writing with both correct address and size.

Stefan
0
 

Author Comment

by:xenia27
ID: 10730087
OK...I got bool type in AStruct...

and now I'm using fwrite(ATree, sizeof(ATree), 1, DataFile);
and nothing is written into the file I want...@@...what's wrong?
0
 
LVL 10

Expert Comment

by:Sys_Prog
ID: 10730092
>>fwrite(&ATree, sizeof(ATree), 1, DataFile)

Why do u require &ATree if ATree is a pointer
Also, sizeof ( ATree ) wont do if ATree is  a pointer
U should use

sizeof(AStruct)

Just
fwrite(ATree, sizeof(AStruct), 1, DataFile)
would do

HTH

Amit
0
 

Author Comment

by:xenia27
ID: 10730105
OK...I got something in my file but the BOOL part didn't written into my file..@@
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:xenia27
ID: 10730116
Sorry...one mistake...the one didn't written into the file is a UINT type...@@
0
 
LVL 10

Expert Comment

by:Sys_Prog
ID: 10730133
Since u are writing the file in Binary mode, u won't be able to see the data using external editors

You will have to read back using fread() to get the data

The code works for me

Amit
0
 

Author Comment

by:xenia27
ID: 10730150
OK...I'm using VC to write my codes...and I set breakpoint around "fread" and try to see what did I write and there is nothing read....

fread(ATree, sizeof(AStruct), 1, DataFile);
and my fwrite
fwrite(ATree, sizeof(AStruct), 1, DataFile);      
0
 
LVL 10

Expert Comment

by:Sys_Prog
ID: 10730167
Go thru this code
Since u are opening the file in "wb" mode, u can just write to the file
So, either close and file & reopen it in "rb" mode OR instead of opening the file in "wb" mode, open it in "rb+" i.e. Read + Write mode




struct data {
      bool b ;
      int  i ;
} ;

int main(int argc, char* argv[])
{
      data d ;
      d.i = 10 ;
      d.b = true ;
      
      FILE *fp = fopen ( "c:\\data.txt", "wb" ) ;
      fwrite ( &d, sizeof ( data ), 1, fp ) ;
      fclose ( fp ) ;
      
       data d1 ;      
      fp = fopen ( "c:\\data.txt", "rb" ) ;
      fread ( &d1, sizeof ( data ), 1, fp ) ;
      fclose ( fp ) ;
      
      cout << d1.i <<endl ;
      cout << d1.b ;
      system("pause");
      return 0;
}
0
 
LVL 10

Assisted Solution

by:Sys_Prog
Sys_Prog earned 100 total points
ID: 10730190
Go thru the following code for the second case example [opening the file in "wb+" OR "rb+" mode]
As shown, remember to use fseek() to position the file cursor t particular location


struct data {
      bool b ;
      int  i ;
} ;

int main(int argc, char* argv[])
{
      data d ;
      d.i = 10 ;
      d.b = true ;
      
      FILE *fp = fopen ( "c:\\data.txt", "w+" ) ;
      fwrite ( &d, sizeof ( data ), 1, fp ) ;
//      fclose ( fp ) ;
      
       data d1 ;      
//      fp = fopen ( "c:\\data.txt", "rb" ) ;
      fseek ( fp, 0, SEEK_SET ) ;
      fread ( &d1, sizeof ( data ), 1, fp ) ;
      fclose ( fp ) ;
      
      cout << d1.i <<endl ;
      cout << d1.b ;
      system("pause");
      return 0;
}


Amit
0
 
LVL 10

Expert Comment

by:Sys_Prog
ID: 10730194
Here is the help for fopen function and different opening modes



Function: FILE * fopen (const char *filename, const char *opentype)

The fopen function opens a stream for I/O to the file filename, and returns a pointer to the stream.

The opentype argument is a string that controls how the file is opened and specifies attributes of the resulting stream.  It must begin with one of the following sequences of characters:

r

Open an existing file for reading only.


w

Open the file for writing only.  If the file already exists, it is truncated to zero length.  Otherwise a new file is created.


a

Open a file for append access; that is, writing at the end of file only.  If the file already exists, its initial contents are unchanged and output to the stream is appended to the end of the file.  Otherwise, a new, empty file is created.


r+

Open an existing file for both reading and writing.  The initial contents of the file are unchanged and the initial file position is at the beginning of the file.


w+

Open a file for both reading and writing.  If the file already exists, it is truncated to zero length.  Otherwise, a new file is created.


a+

Open or create file for both reading and appending.  If the file exists, its initial contents are unchanged.  Otherwise, a new file is created.  The initial file position for reading is at the beginning of the file, but output is always appended to the end of the file.

HTH

Amit
0
 
LVL 8

Accepted Solution

by:
ssnkumar earned 150 total points
ID: 10730760
>fread(ATree, sizeof(AStruct), 1, DataFile);
>and my fwrite
>fwrite(ATree, sizeof(AStruct), 1, DataFile);

If both the statements are coming one next to another, then what you have done is absolutely wrong!
In your 1st post I see that the file is opened in "write" mode. Then how can you use fread() on this stream which is open for writing!?
Even if you have opened the file in append mode, first you should position the file pointer at correct postion before doing fread and fwrite. Otherwise, you may overwrite the existing contents!

>Sometimes it works fine but sometimes it doesn't.  What should I do??
How are you verifying if it has been written correctly or not? Is it by opening the file and looking at the contents or by using another program with same data structures to read the data and then displaying!?
2nd method will only give you the correct result.....

-ssnkumar
0
 

Author Comment

by:xenia27
ID: 10730859
I use another program to read the data...most of time, it works...but sometimes there is no data written in the file...still trying to figure out how would that happen.  @@  Is there anything happened will cause this result?  Any idea???
0
 
LVL 8

Expert Comment

by:ssnkumar
ID: 10731281
The only possible reasons are:
1. The reading and writing are happening with different data types/structures.

You can try one thing.
Comment out all other operations other than write to the file.
Similerly in the program which you read, comment out everything else other than read.
Now you can clearly see what is happening.
If it is not a huge code, you can post both read and write routines so that we can also analyze.....

-ssnkumar
0
 
LVL 12

Assisted Solution

by:stefan73
stefan73 earned 150 total points
ID: 10731282
>sometimes there is no data written in the file

stdio is buffered (and also doesn't mix well with C++'s iostream). Check that you did either fclose or fflush on your file before you try to read it with annother application.
0
 
LVL 12

Expert Comment

by:stefan73
ID: 10733356
ssnkumar,
> how can you use fread() on this stream which is open for writing!?
On many systems you can.

Stefan
0
 

Author Comment

by:xenia27
ID: 10737632
OK...thanks for all the info...I follow all the steps but something is still wrong...I guess it's not the problem I thought it was...anyway, thanks for the info...they are helpful!!
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

911 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now