C ++: opening a file in non-exclusive mode

I need to develop an application that parses a log file and sends certain data to the server. It should work on both Linux and Windows.

The problem occurs when I want to test a logging system (which adds .1 to the creation name of a new one with the same name). On Windows (not yet tested on Linux), I cannot rename the file that I opened with std :: ifstream () (exclusive access?), Even if I open it in the "input mode" (ios :: in).

Is there a cross-platform way to open a file in a non-exclusive way?

+4
source share
5 answers

Is there a way to open the file in a non-exclusive way,

Yes, using Win32, passing various FILE_SHARE_Xxxx flags to CreateFile.

is it a cross platform?

No, this requires platform-specific code.

Due to annoying backward compatibility (DOS applications, being single-tasking, assume that nothing can remove a file from under them, i.e. that they can fclose () and then fopen () without any changes, Win16 saved this assumption is to facilitate the transfer of DOS applications, Win32 has retained this assumption to simplify the transfer of Win16 applications, and this is terrible), Windows by default opens files exclusively.

The main OS infrastructure supports deleting / renaming open files (although I believe that it has a restriction that memory mapped files cannot be deleted, which, I think, is not a restriction on * nix), but the default semantics of opening are do not do it.

C ++ has no idea about this; The C ++ operating environment is almost the same as the DOS operating environment - no other applications running at the same time, so there is no need to control file sharing.

+3
source

This is not a read operation requiring exclusive mode, it is a renaming, because it is essentially the same as moving a file to a new location.

I am not sure, but I do not think it can be done. Try copying the file and then delete / replace the old file when it is no longer being read.

+1
source

The semantics of the Win32 file system require that the file you rename not be open (in any mode) during rename. You will need to close the file, rename it and create a new log file.

The Unix file system semantics allows you to rename a file that opens because the file name is just a pointer to an index.

+1
source

If you are only reading from a file, I know that this can be done using the windows api CreateFile. Just specify FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE as an input to dwShareMode.

Unfortunately, this is not cross-platform. But for Linux, there might be something similar.

See msdn for more information on CreateFile .

EDIT: Just a quick comment on Greg Huglill's comment. I just tested the material FILE_SHARE * (also 100% sure). And you can delete and rename files in Windows if you open read-only and specify the FILE_SHARE * parameters.

+1
source

I would make sure that you do not keep the files open. This leads to strange things, for example, when the application crashes. What will i do:

  • Annotation (read / write / transition to a new file) in one class and ordering the closing of the file when you want to switch to a new one in this class. (This is the most neat way, and since you already have a brute force code, you're halfway there.)
  • If you have several read / write access points, you need all the fstream functions and you don't want to write to fill the shell, then the only cross-platform solution I can think of is to always close the file, t need it , and the overflow code attempts to gain exclusive access to the file several times when it needs to be flipped before refusing.
0
source

Source: https://habr.com/ru/post/1276436/


All Articles