Is it possible to set somehow these flags when using TFileStream?
Any other solution that includes Delphi wrapper functions for
Windows API that include these flags?
so no answer needed I guess...
You need explicitly TFileStream class? Or it is enough to have its
functionality? If latter one, use this:
uses
windows, consts, Classes;
type
type
TFileStreamEx = class(THandleStream)
public
constructor Create(const FileName: string; Mode: Word; flags: DWORD
= FILE_ATTRIBUTE_NORMAL);
destructor Destroy; override;
end;
constructor TFileStreamEx.Create(const FileName: string; Mode: Word;
flags: DWORD = FILE_ATTRIBUTE_NORMAL);
const
AccessMode: array[0..2] of LongWord = (
GENERIC_READ,
GENERIC_WRITE,
GENERIC_READ or GENERIC_WRITE);
ShareMode: array[0..4] of LongWord = (
0,
0,
FILE_SHARE_READ,
FILE_SHARE_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE);
begin
if Mode = fmCreate then
begin
inherited Create(
CreateFile(
PChar(FileName),
GENERIC_READ or GENERIC_WRITE,
0,
nil,
CREATE_ALWAYS,
flags,
0
)
);
if Handle < 0 then
raise EFCreateError.CreateFmt(SFCreateError, [FileName]);
end
else
begin
inherited Create(
CreateFile(
PChar(FileName),
AccessMode[Mode and 3],
ShareMode[(Mode and $F0) shr 4],
nil,
OPEN_EXISTING,
flags,
0
)
);
if Handle < 0 then
raise EFOpenError.CreateFmt(SFOpenError, [FileName]);
end;
end;
destructor TFileStreamEx.Destroy;
begin
if Handle >= 0 then CloseHandle(THandle(Handle));
end;
///////////////////////////////////////////////////
This class basically works like TFileStream, but allow You to specify
flags to CreateFile(). If You leave "flags" param at its default value
(FILE_ATTRIBUTE_NORMAL) it will work exactly like original TFileStream.
You can use it like this:
... := TFileStreamEx.Create('filename', fmCreate, FILE_ATTRIBUTE_NORMAL
or FILE_FLAG_NO_BUFFERING or FILE_FLAG_WRITE_THROUGH).
BTW, You may also want to use FILE_ATTRIBUTE_NORMAL or
FILE_FLAG_SEQUENTIAL_SCAN hints flags to optimize performance.
Note: if some function require TFileStream, You may cast TFileStreamEx
to TFileStream. All properties and methods are shared, and objects are
binary compatible. But if function explicitly check object class at
runtime(using operator "as" for example), check will fail.
--
Arivald
FlushFileBuffers(MyStream.Handle);
For that matter, you could create an inherited class of your own that
would call that each time a "WRITE" function was executed.
Btw, the file handle should be 0 if not valid.. you are testing for
- values here, I don't think that is correct. If there is a problem
during opening, the TFileStream.Create should return an error, also,
if you are building your own class you must override the Create
(constructor) and call the inherited first before checking the handle
other wise, you're going to get wild stuff!
Jamie
But it is not same functionality.
> There may be difference in performance but that difference is small for my
> needs (I haven't really seen any difference).
>
> Simply FlushFileBuffers after a large enough chunk of buffer has been sent
> to disk - 16 kb or more. That way it will be quite fast.
Calling FlushFileBuffers after 16 kb is basically useless. Windows file
cache manager use 4 kb pages, so after 16 kb write buffer should be
already scheduled to write. Calling FlushFileBuffers only stop your
program execution until it really happens, and data are really send to
disk controller.
BTW, what You need this option for?
For me, I used it only to log data in some debug builds, when
application crash may happen. This way I'm sure that all data are logged.
--
Arivald