1

I basically want to open a file and read but also make changes to it in binary, if it exists, and I want the file to be created if it doesn't. Thus, 'ab+'. No issues there.

However, I essentially want to see if the file existed before it was created by 'ab+', since if it didn't, then there is no need to read in the contents (we can be guaranteed it is empty). Basically a lengthy part of the code could then be skipped over, if I make it as if only the file existed prior to it being created by the fopen 'w' or 'a' modes. However it seems wasteful to try (succeeding most of the time too) and open a file in read mode each time, close it, and open the same file again in append binary mode.

It's honestly not a major issue. Just curious. Is a more convenient way possible? I'm on a windows platform using MSVisio.

Terrornado
  • 793
  • 3
  • 9
  • 21
  • 5
    Well, you could `stat`/`lstat` it. I *think* it would be a bit faster, but I haven't checked. Also, depending on your application, beware that this double-check introduces a race condition between your process and the rest of the OS. – Yoric May 31 '18 at 13:26
  • 1
    Possible duplicate of [What's the best way to check if a file exists in C? (cross platform)](https://stackoverflow.com/questions/230062/whats-the-best-way-to-check-if-a-file-exists-in-c-cross-platform) – Fabio_MO May 31 '18 at 13:33
  • 1
    What should happen if the file gets created *between* the time you check for its existence, and the time you try to open it? – Steve Summit May 31 '18 at 13:37
  • You could check if the file is empty after opening it, for example using `fseek` and `ftell` (or perhaps some platform-dependent equivalent for large files on some platforms). – Ian Abbott May 31 '18 at 13:39
  • 2
    It seems to me that the "lengthy part of the code" that reads in the existing file will have no work to do if the existing file is empty. You could call `fstat` to determine the file's size, and skip the initial read if the file size is 0. Or, even more simply, you could have the initial file-reading code detect EOF and skip the rest of itself. (The code is probably doing that today, if it's working properly in the case where the file just got created.) – Steve Summit May 31 '18 at 13:40
  • *However, I essentially want to see if the file existed before it was created by 'ab+', since if it didn't, then there is no need to read in the contents* That's a [TOCTOU bug](https://en.wikipedia.org/wiki/Time_of_check_to_time_of_use) along with being a pretty poor design. There's never any reason to "check for X before doing Y". X is not Y, so on top of being a TOCTOU bug, the check X won't be definitive for doing Y anyway. Just open the file, read what's in it, and if it was nothing you have nothing to do before writing. – Andrew Henle May 31 '18 at 14:04
  • You should open in `ab+` and then `ftell` to check if the file is empty or not. If `ftell(...)` returns `0`, your file didn't exist (or was empty) and you can skip your lengthy code. I assume it doesn't matter to the lengthy code if the file didn't exist or was empty. – Ajay Brahmakshatriya May 31 '18 at 14:09
  • Are you sure you want `ab+` and not `rb+`? The `a` (append) means all 'modifications' will be added at the end of the file; you can't write anywhere but at the end of the file using the standard I/O library. – Jonathan Leffler May 31 '18 at 14:40
  • @IanAbbott You can't escape platform dependencies in getting the size of a file for any method other than reading byte-by-byte and counting. [`fseek()` to the end of a binary stream is explicitly UB](https://port70.net/~nsz/c/c11/n1570.html#note268), and [`ftell()` on a text stream does not return a byte offset.](https://port70.net/~nsz/c/c11/n1570.html#7.21.9.4p2) When you use those functions to get the size of a binary stream, you're relying on *platform specific* details such as the POSIX guarantee that you can seek to the end of a binary file. – Andrew Henle May 31 '18 at 14:41
  • @AndrewHenle Okay, you don't need to know the size though, you only need to know if its empty or not. – Ian Abbott May 31 '18 at 14:48

0 Answers0