Recent

Author Topic: What is the easiest way to flush the buffer to disk.  (Read 1167 times)

CaptBenB

  • Newbie
  • Posts: 5
What is the easiest way to flush the buffer to disk.
« on: June 16, 2024, 03:56:53 am »
The first few lines work as expected.  However, I get errors about ...'arg no. 1 has to match exactly: Got "ansistring" expected "Text"'....
when attempting to Flush the dbName, I get an error on close as well.

The goal is to create an empty file when one does not exist and skip the creation if it does exist without errors of course.

The issue is that when the file is not 'Flushed' to disk, the subsequent SQL statements fail b/c the file does not exist on disk yet.  Once the file exists, all the sql statements work.

I've read some on the pointers, and PChar, and single character files, ... it's kind of jumble in my head.  Any help is appreciated.


Code: Pascal  [Select][+][-]
  1.  
  2.   // -------------------------------------------------------------
  3.   // -- create the db if it does not exist
  4.   // -------------------------------------------------------------
  5.   dbName := IncludeTrailingPathDelimiter(GetCurrentDir()) + 'test.db';
  6.   If FileExists(dbName)=False Then FileCreate(dbName);           // -- create it
  7.   If FileExists(dbName)=True Then  FileOpen(dbName,fmOpenRead);  // -- open for read
  8.   If FileExists(dbName)=True Then  Flush(dbName)                 // -- flush buffer to disk)
  9.   If FileExists(dbName)=True Then  FileClose(dbName);            // -- close it
  10.  

Red_prig

  • Full Member
  • ***
  • Posts: 152
Re: What is the easiest way to flush the buffer to disk.
« Reply #1 on: June 16, 2024, 04:07:04 am »
If you are using a database you should use the interface of the database you want to use (I don't understand which one you mean).
 FileCreate/FileOpen/Flush/FileClose is a more general file interface that you are trying to use in a strange way (you clearly haven't read the documentation)


TRon

  • Hero Member
  • *****
  • Posts: 2836
Re: What is the easiest way to flush the buffer to disk.
« Reply #3 on: June 16, 2024, 05:51:24 am »
The first few lines work as expected.  However, I get errors about ...'arg no. 1 has to match exactly: Got "ansistring" expected "Text"'....

https://www.freepascal.org/docs-html/rtl/sysutils/fileexists.html

Quote
Check whether a particular file exists in the file system.

Code: [Select]
function FileExists(const FileName: UnicodeString; FollowLink: Boolean = True):Boolean;


Quote
Code: [Select]
If FileExists(dbName)=False Then FileCreate(dbName);           // -- create it

https://www.freepascal.org/docs-html/rtl/sysutils/filecreate.html

Quote
Create a new file and return a handle to it.

Code: [Select]
function FileCreate(const FileName: UnicodeString):THandle;
...



Quote
Code: [Select]
  If FileExists(dbName)=True Then  FileOpen(dbName,fmOpenRead);  // -- open for read

https://www.freepascal.org/docs-html/rtl/sysutils/fileopen.html

Quote
Open an existing file and return a file handle

Code: [Select]
function FileOpen(const FileName: unicodestring; Mode: Integer):THandle;


Quote
Code: [Select]
  If FileExists(dbName)=True Then  Flush(dbName)                 // -- flush buffer to disk)

https://www.freepascal.org/docs-html/rtl/sysutils/fileflush.html

Code: [Select]
function FileFlush(Handle: THandle):Boolean;

note the handle parameter.

Quote
Code: [Select]
  If FileExists(dbName)=True Then  FileClose(dbName);            // -- close it

https://www.freepascal.org/docs-html/rtl/sysutils/fileclose.html

Quote
Close a file handle.

Code: [Select]
procedure FileClose(Handle: THandle);


But ofc. it is always easier to ask on the forums than it is to read the documentation... so right back at you  ;D

BTW:
Code: Pascal  [Select][+][-]
  1. var
  2.   dbName: string;
  3.   fh : THandle;
  4. begin
  5.   dbName := IncludeTrailingPathDelimiter(GetCurrentDir()) + 'test.db';
  6.   if not FileExists(dbName) then
  7.   begin
  8.     fh := FileCreate(dbName);           // -- create it
  9.     // do something with the file such as writing data to it
  10.     FileClose(fh);
  11.   end;
  12.  
  13.   if FileExists(dbName) then
  14.   begin
  15.     fh := FileOpen(dbName, fmOpenRead);  // -- open for read
  16.     // make sure the filehandle is valid
  17.     if fh <> feInvalidHandle then
  18.     begin
  19.       // do something with the file such as writing data to it
  20.       if FileFlush(fh)         // -- flush buffer to disk)
  21.         then writeln('data was flushed');
  22.  
  23.       FileClose(fh);            // -- close it
  24.     end;
  25.   end;
  26. end.
  27.  

Flushing usually only makes sense when using a file in read/write mode and actually read and write to it simultaneously.
« Last Edit: June 16, 2024, 05:53:13 am by TRon »

MarkMLl

  • Hero Member
  • *****
  • Posts: 7037
Re: What is the easiest way to flush the buffer to disk.
« Reply #4 on: June 16, 2024, 09:43:37 am »
The first few lines work as expected.  However, I get errors about ...'arg no. 1 has to match exactly: Got "ansistring" expected "Text"'....

OK, /stop/ /right/ /there/.

Number one rule: when you submit a test fragment, it should be an entire program so that other people can compile it and see what's happening.

You've also not told us what OS you're using, hence what API that FileOpen etc. is associated with. However ISTR that you were asking about Macs in another thread...

Those low-level calls return results, which you're ignoring. In particular, FileOpen() returns a low-level handle which you're supposed to use for subsequent actions.

But when you call Flush(), it's from a different API, and it's expecting a parameter of type "text", which is much higher-level.

I suggest that now would be a good time to take a superficial look at https://www.freepascal.org/docs.html so that you know roughly how the various sources of information are laid out. However what you need right now is the RTL reference, and if you look at the top-left of that page you'll find there's an index of all function/procedure names which will lead you to FileExists() etc.

So your error message said 'Got "ansistring" expected "Text"'', which is confusing since you don't understand what "a text" is. But in short your dbName is a constant string which defaults to type "ansistring", while the type "Text" referred to is not some other sequence of characters but is an opaque type representing a higher-level file.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

CaptBenB

  • Newbie
  • Posts: 5
Re: What is the easiest way to flush the buffer to disk.
« Reply #5 on: June 16, 2024, 04:58:37 pm »
Thank you for responding this is very helpful! 

tldr:
-----
Thank you TRon for the code, that helps a lot! 

Thank you MarkMLI as well for your thorough explanation.  Especially these lines....

...hence what API that FileOpen etc. is associated with...

...In particular, FileOpen() returns a low-level handle which you're supposed to use for subsequent actions...

...when you call Flush(), it's from a different API, and it's expecting a parameter of type "text", which is much higher-level....

...your dbName is a constant string which defaults to type "ansistring", while the type "Text" referred to is not some other sequence of characters but is an opaque type representing a higher-level file....


Long Version:
--------------
I am new to this forum and apparently still need to learn some of the basics.  Thank you for being patient with me while I learn the ropes.

For your reference, I am 61 years old, have been involved with computers in one way or another since 1978.

I switch OS platforms often and quickly.  I have Linux, Windows, Mac all active online all the time.  Each has specific functionality for programs that I run that will not run on the other - except Linux which is used outside of my main daily job for some personal website stuff.

I have used several cross platform program languages over the years but most of the languages I have used take into account many of these little details for file handling. 

I understand that the closer to machine code you go, the more that has to be dealt with.  My favorite code in college was assembler, but also very long to do any little thing.   

I had written a program in Lazarus/Freepascal for work about ten or so years ago and it worked well and kept us going.  However, I found it a bit cumbersome at the time for design and coding speed.  Businesses seem to need solutions quickly (go figure).  So I switched back to a language I know much better for quicker design.  Allthough it is an excellent language, annual cost and maintenance for plugins, are considerable.

Since I'm approaching the end of my working career,  I'm wanting to switch back to Freepascal / Lazarus to save what would be an otherwise unbearable cost after retirement.
I tend to plan years ahead and this is one of those times.

When perusing the documentation, I came across the links you mentioned above.  However there were some key pieces of basic information that I had forgotton and other pieces I just didn't understand.

Your explanations have and will help me a lot going forward.  I will test them (and fix my broken code) over the next few weeks.


MarkMLl

  • Hero Member
  • *****
  • Posts: 7037
Re: What is the easiest way to flush the buffer to disk.
« Reply #6 on: June 16, 2024, 07:11:25 pm »
For your reference, I am 61 years old, have been involved with computers in one way or another since 1978.

Youngster :-)

Sorry, I didn't have very much time this morning since I was committed to some volunteering work.

Basically, there are several possible levels in the filehandling hierarchy.

At the lowest level, you can use OS-specific calls that work with handles. For example on Linux you'd import BaseUnix and then have fpOpen() etc.; I believe that a Mac uses an OS derived from the BSD family so it would have something similar if not identical.

At a slightly higher level you could use FileOpen(), which similarly returns a handle which you subsequently use for data handling passing the address and size of a data block.

At a higher level, you could use Assign(), Reset() and Rewrite(). These work with a variable generally declared as "file of sometype", where the size of sometype determines the record size on disc. This is one of the two filehandling types you will find in books on what I might call "traditional Pascal", and if you have mainframe experience corresponds to the fixed-length record structure inherited from batch systems (i.e. cards etc.).

Alternatively. you could use Assign() etc. with a variable of type text, which is where your Flush() comes in. This is the other traditional filehandling API, and is used with WriteLn() etc., records are inherently variable-length and textfiles aren't seekable.

Then there's streams, which a lot of people prefer these days.

Finally, there's the much higher level access methods associated with database APIs, i.e. SQL etc., hence somebody's comment that you wouldn't normally do an explicit flush of a database file (I think they were misled by the name of your dbName variable). I'd urge you to consider using a backend SQL database (SQLite, PostgreSQL etc.) if data integrity is important, or if there is any chance whatsoever that more than one program or user will need simultaneous access.

HTH.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

TRon

  • Hero Member
  • *****
  • Posts: 2836
Re: What is the easiest way to flush the buffer to disk.
« Reply #7 on: June 17, 2024, 04:51:18 am »
Thank you TRon for the code, that helps a lot! 
You are most welcome.

Do note that my example was a quick mockup and there are some inconsistencies in there (I did not check the fliehandle after the file creation for example) and I used fileflush instead of your used flush (which MarkMLI correctly stipulated to work on different types of files).

Quote
I am new to this forum and apparently still need to learn some of the basics.  Thank you for being patient with me while I learn the ropes.
We all started somewhere and some have more difficulty understanding the descriptions of the manual and used concepts than others.

Do note that besides the manuals there is a wiki that can be searched that usually have examples of/for the most common used API's. There are also examples accompanied with FPC and Lazarus but if you are new and/or renewing your knowledge then that might perhaps be a bit steep to follow.

Quote
For your reference, I am 61 years old, have been involved with computers in one way or another since 1978.
I concur with MarkMLI... you are still a youngster (admittingly not by much but still) :)

The usage of files as shown in your example might be the wrong approach and depend more on what it is that you are actually trying to achieve (as also described by MarkMLI) so in case of questions then just ask  :)

If you are comfortable enough with the language then Free Pascal/Lazarus is (at least for me) a very quick way to solve problems. The more knowledge on the API's, classes and the Pascal language itself the quicker/easier things can be solved. Do note I am biased towards Pascal and in particular FPC/Lazarus.

Whatever the case for you try to have at least some fun !

Zvoni

  • Hero Member
  • *****
  • Posts: 2461
Re: What is the easiest way to flush the buffer to disk.
« Reply #8 on: June 17, 2024, 07:57:14 am »
Since SQL was mentioned, and seeing those code snippets, i'm going out on a Limb and say, it's SQLite.

Why in blazes even using those "File"-Functions?
SQLite3conn creates the db-file if it doesn't exist
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

 

TinyPortal © 2005-2018