Reputation: 4840
My application reads a TextFile of floating point numbers slowly. From time to time circumstances change and the file has to be rewritten. Some example code:
procedure TAMI_Column_Selector.read_continuously (file_name: string);
var infile: TextFile;
f: Double;
begin
AssignFile (infile, file_name);
Reset (infile);
try
while not EOF (infile) do
begin
Read (infile, f);
process (f); // this may take quite some time, seconds or even minutes
end; // while
finally
CloseFile (infile);
end; // try..finally
end; // read_continuously //
How can I write a file that is open for reading? More specifically:
I think I could solve the first to questions be reading the file into memory and read that (is there a TextFile that can be written to and read from memory)? Then still remains how I can test a file has been written over.
Anyone having an (elegant) solution to this problem?
Thanks in advance.
Using Delphi XE on windows 7
Upvotes: 4
Views: 2183
Reputation: 163287
To write to a file that's also open for reading, there's generally not anything special the writer needs to do. If everyone else who has the file open has allowed writing to the file, then the intended writer can open the file for writing, write to the file, and close it. If the others haven't allowed writing to the file, then the intended writer won't be allowed to open the file in the first place, and there's nothing it can do about it.
How to open a file for reading while also allowing writing depends on the opening method being used. With CreateFile
, the dwDesiredAccess parameter is the usual GENERIC_READ
, and the dwShareMode parameter is FILE_SHARE_READ or FILE_SHARE_WRITE
. If you're using a TFileStream
, then the mode parameter of the constructor should be fmOpenWrite or fmShareDenyNone
. If you're using AssignFile
and Reset
, then you'd need to set the FileMode
global variable, but that doesn't support any sharing modes, so you can't use Pascal-style I/O.
Reading a file that is at the same time being written does not inherently cause a crash. It certainly doesn't cause problems at the OS level. If your program crashes, it's because it wasn't written to anticipate reading failures. When you read something, check the API result to confirm that you read as many bytes as you requested. You can also have the reading and writing applications communicate with each other. You might use a synchronization object to serialize access to the file, or the writer might send the reader a signal to indicate that the file has changed, and that the previous read might not be accurate anymore. It's up to you to work the details.
If the reader is going to keep a copy of the file in memory, then it probably doesn't need to bother sharing write access. Instead, it can open the file and only share read access, make a copy of the file in memory, and the close the file. The writer can then open the file without any worries of trampling on the reader process because there's nothing to trample. It can notify the reader that something changed, and the reader can either reload the entire file or just load the part that changed. (The writer will have to tell the reader which part changed, though; there's no other way for the reader to detect that without reading the entire file and seeing how it differs from the memory copy.)
Another way to keep writes from interfering with reads is to use transactions. Transactional NTFS is being phased out, though. Microsoft has published a list of alternatives, so you can try to find something that matches your needs.
Upvotes: 4