file modes wb vs wb+

zizi21
zizi21 used Ask the Experts™
on
hi,

i have a file that i am writing and reading. If I open at as wb+, the time to run a file is about 5 seconds and if I left it as wb, the time is 9 seconds.

Is there a difference using wb and wb+ ?

Tks.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Are you doing error handling on every I/O call?

From     http://www.cplusplus.com/reference/clibrary/cstdio/fopen/
w ==   Create an empty file for writing.
w+ == Create an empty file for both reading and writing.
(the b is just binary file).

I am surprised about the time difference if you are only writing. If reading also, then "wb+" should be the only one that works.

Author

Commented:
I am doing reading and writing and there is a couple of other weird issues too..

when i do wb, this works
p=ftell(fp);      
if(c > p)
{
   f= c - p;
   fseek(fp,f,SEEK_CUR);
}
else if(c< p)
{
     b=p - c;
  fseek(fp,-b,SEEK_CUR);
}

but it doesn't work properly when i do wb+. in order for it to code with wb+, i need to add the extra else..

else
{
     fseek(fp,0,SEEK_CUR);
}

I face this issue on mac..but it seems to work fine (without the else on a linux server..)

Author

Commented:
that's why I thought, it is a file mode issue..
in this file, i could write a character and then, the next moment, i could also read the character that i have just written.
Acronis in Gartner 2019 MQ for datacenter backup

It is an honor to be featured in Gartner 2019 Magic Quadrant for Datacenter Backup and Recovery Solutions. Gartner’s MQ sets a high standard and earning a place on their grid is a great affirmation that Acronis is delivering on our mission to protect all data, apps, and systems.

>> I am doing reading and writing
>> when i do wb, this works
>> write a character and then, the next moment, i could also read the character that i have just written.

How does your read work if "wb"? Doesn't that give an I/O error since you are opening the file for write-only?

Author

Commented:
it doesn't give any error thats why it is weird..
I'll try to see for myself (unless you have a small program to illustrate the problem).

>> p=ftell(fp);      
>> if(c > p)
>> else if(c< p)
>> doesn't work properly when i do wb+.

1) In this if..else, what did you want to do when c==p ?
2) What is the operation you do (read or write) before the ftell?
3) What is the operation you do (read or write) after the if..else?
4) Please explain what does not work properly? (If you already explained it, please elaborate. Thanks.)

Author

Commented:
sorry the program is really huge..my assignment....i am not suppose to post anything on the web ..which is really bad as posting it could discover the problem ....sorry...

if(c == p)..it means, i think, is that don't move the file pointer which seems to be moving...by doing this
   fseek(fp,0,SEEK_CUR); i seem to tell the file pointer dont go any where which is very strange...

Author

Commented:
2)2) What is the operation you do (read or write) before the ftell?

before ftell, i did a write if there was a need as at times, you don't to do a write...
then, after ftell, i wrote the elements...and i set the position again.. using the piece of code that i posted..

Author

Commented:
3) What is the operation you do (read or write) after the if..else?
After if else, i might do a write if it is needed,

Author

Commented:
"if(c == p)..it means, i think, is that don't move the file pointer which seems to be moving...by doing this
   fseek(fp,0,SEEK_CUR); i seem to tell the file pointer dont go any where which is very strange..."

here seems to be the problem...as when i do this, i am getting correct output...
>> by doing this fseek(fp,0,SEEK_CUR);
>> here seems to be the problem...as when i do this, i am getting correct output...

Could you clarify what precisely the incorrect output is when you do not do this? Does it go wrong all the time (whether doing a read or write)? If doing a write, I take it that the data is being put into the wrong position.

===
One interesting thing you mentioned.
>> I face this issue on mac..but it seems to work fine (without the else on a linux server..)

I am completely unfamiliar with mac. Perhaps you can decide whether these two points are related to the different platforms:

fopen:
"You can also optionally specify the “b” flag to open a file in binary mode on Windows systems. This flag is ignored on POSIX systems (including Linux), so it's safe to always specify this flag when operating on binary files."
     http://www.cppreference.com/wiki/c/io/fopen

fseek:
"When using fseek on text files with offset values other than zero or values retrieved with ftell, bear in mind that on some platforms some format transformations occur with text files which can lead to unexpected repositioning."
     http://www.cplusplus.com/reference/clibrary/cstdio/fseek/
>> my assignment....i am not suppose to post anything on the web ..which is really bad as posting it could discover the problem

If assignment, then agreed - don't post the whole program. But if you wrote a mini-program having nothing to do with the essence and details of your assignment, but just had plain old I/O operations, then is there anything wrong with posting that? And then, if there is some behavior in this mini-program that you want to discuss, isn't that permissible?
>> it doesn't give any error thats why it is weird..
Please check your error handling. See my error handling below.

Funny, am I allowed to post my code based on your words??

On Cygwin, using "wb", below code produces output:
$ ./a
read error: Bad file descriptor

On Visual Studio 2008 Express, you just get a stupid error message:
        read error: No error
(But that's just MS
   
Change it to "wb+", and no error on Cygwin and VS 2008 Express.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFFSIZE (4096*16)

int main(int argc, char *argv[])
{
   FILE * fp;
   int    n;
   char   buf[BUFFSIZE];
   char   bf2[BUFFSIZE];
   char filename[] = "test_fseek_wb.out";

   for(n=0; n < BUFFSIZE; n++ ) {
      buf[n] = n;
   }

   fp = fopen( filename, "wb");
   if( fp == NULL ) {
      perror("fopen wb");
      exit(-97);
   }

   n = fwrite( buf, 1, BUFFSIZE, fp);
   if( n != BUFFSIZE ) {
      perror("write error");
      exit(-99);
   }

   fseek(fp, 256, SEEK_SET );
   n = fread( bf2, 1, 256, fp );
   if( n != 256 ) {
      perror("read error");
      exit(-99);
   }
   exit(0);
}

Open in new window

Author

Commented:
Could you clarify what precisely the incorrect output is when you do not do this? Does it go wrong all the time (whether doing a read or write)? If doing a write, I take it that the data is being put into the wrong position.
yes, data is being put into the wrong position

Author

Commented:
Funny, am I allowed to post my code based on your words??
Thanks for posting...i wouldn't copy...i dont know where the problem is ...maybe, i am a bit tired right now...sorry..just give me a bit of time, and i would post a mini program...
>> yes, data is being put into the wrong position
Exactly how far off and in what direction?

Author

Commented:
i got bad file descriptor with your code and not with mine..

fp= fopen(file,"wb"); //"wb+");
      if(fp==0)
      {
            fprintf(stderr,"\nCannot opent file.\n");

      }

is there a problem with this way ?
>> read error: Bad file descriptor
Firstly, notice that this message resulted from an error while doing a fread.

You posted code related to fopen error handling. Did you have an error with fopen? I don't have errors there. However, since you posted it, my comment is that the error test is:
     if( fp == NULL )
since it is possible for NULL to be non-zero on some systems (I've never seen it, but I have to go by what I read).

If you look at http://www.cplusplus.com/reference/clibrary/cstdio/fopen/ you see in the Return Value section is the statement:
"If the file has been succesfully opened the function will return a pointer to a FILE object that is used to identify the stream on all further operations involving it. Otherwise, a null pointer is returned."

Since a null pointer is returned as an error indicator, then you should test for a null pointer, and not 0.

Author

Commented:
it works on linux systems but not on unix systems...it could be a portability issue.
What read error handling do you do? Is it similar to what I posted?

>   fseek(fp, 256, SEEK_SET );
>   n = fread( bf2, 1, 256, fp );
>   if( n != 256 ) {
Notice that is tested for n!=256 because I knew from the fseek that I should be able to read the full 256 bytes since I was not near the end of file.

Are you saying that the fread does not return an error in "wb" mode? And, if it does not return an error, are you saying that you actually are reading the data in correctly? This is surprising.

Author

Commented:
it works on linux systems but not on unix systems...it could be a portability issue.

what i meant by this is that , the code works fine on linux system and not on unix system..

">> yes, data is being put into the wrong position
Exactly how far off and in what direction?"
here, instead of jumping 4 bytes after a write, it jumped 3924 bytes...
Top Expert 2009

Commented:
>> Since a null pointer is returned as an error indicator, then you should test for a null pointer, and not 0.

Both are the same thing. Even if the actual value of a null pointer is not an all-zero pointer, it is still safe to compare with either NULL or 0. The compiler has to do what's right to make it work.

All these are equivalent :

        if (ptr == NULL)
        if (!ptr)
        if (ptr == 0)


With regards to the question : it seems to me there is something in your code that you haven't mentioned. If you cannot post the whole code, please construct a minimal (complete and compilable) sample that exhibits the same behavior, and post that here (like phoffric suggested earlier).
Thanks for clarification about NULL... :)

Now, trying to understand one thing (at a time).

When you open using "wb", you say that you are able to read on one of the platforms.
What value do you get for n in your corresponding fread statement?
            n = fread( bf2, 1, 256, fp );

And does your buffer fill up with the correct results? Using "wb", it should not; and your return value should indicate an error.

When you open with "wb", could you add a statement like:
               char bf2[100]; // large enough to hole 4 bytes.
               n = fread( bf2, 1, 4, fp );
and verify that n == 4, where the file is well before the EOF. Then confirm that n == 4 (it shouldn't) and that bf2 is filled correctly (it should not change).

I just would like to confirm your findings that fread produces no errors when using "wb".

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial