_I_Play_Chess
11-29-2003, 11:51 AM
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD colSpan=2>Creating flat (non-relational) databases with no database components <!-- End of Headline --></TD></TR>
<TR>
<TD bgColor=#cc0000 colSpan=2 height=1><IMG height=1 src="http://images.about.com/all/bullets/dot_clea.gif" width=1 border=0></TD></TR>
<TR>
<TD colSpan=2>Delphi Personal edition does not offer database support. In this chapter, you will find out how to create your own *flat* database and store any kind of data - all without a single data aware component. <!-- End of Subhead --></TD></TR>
<TR>
<TD colSpan=2><IMG height=6 src="http://images.about.com/all/bullets/dot_clea.gif" width=1></TD></TR></TBODY></TABLE>Welcome to the fifteenth chapter of the FREE online programming course:
<H5 style="PADDING-LEFT: 10px; MARGIN-BOTTOM: 0px; COLOR: #000080">No DB support in Delphi Personal edition</H5>As you probably know, Delphi Personal edition comes with no database support, in terms of data-aware components. Hopefully, "data world" isn't only about Paradox, Access, Interbase or MySQL.
The data your application needs to operate on may not always be stored in a relational database. It may be stored in an ASCII text file or a structured binary file. It may even be stored in an XML file. As you will learn from this chapter, your application can read data from a file (of *any* structure), update "fields", add new "records", and write data back to the file as if the data were stored in a *real* database. NOTE: flat-file databases are not as scaleable (and safe) as the relational model databases (MySQL, MS SQL Server, Interbase, etc). If you are only working with a small amount of data that is rarely updated then a flat-file database could be your choice.
However, if you are looking for a database for more frequent and heavy use then a relational database is probably more suitable.
Files from Delphi perspective:
Simply put a file is a binary sequence of some type. In Delphi, there a three classes of file: typed, text, and untyped. Typed files are files that contain data of a particular type, such as Double, Integer or previously defined custom Record type. Text files contain readable ASCII characters (organized into lines). Untyped files are used when we want to impose the least possible structure on a file.
<H5 style="PADDING-LEFT: 10px; MARGIN-BOTTOM: 0px; COLOR: #000080">Building your own database system</H5>The next series of articles shows you how to use Delphi to create a simple "database" application that interacts with data in text (ASCII) or binary files:
<H3>TEXT FILES IN DELPHI
Handling ASCII files from Object Pascal code.</H3> <B>The world isn't only about Paradox, Access, Interbase, MySQL, MS' SQL Server ...</B>
Simply put, <I>text files</I> contain readable ASCII characters. We can think of working with text file in Delphi as analogous to playing or recording information on a cassette tape.
Although it is possible to make changes within text file, jump around when processing information or add some data to the file other than at the end, it is advisable to use a text file only when we know that we are working with ordinary text and no such operations are necessary.
Text files are considered to represent a sequence of characters formatted into lines, where each line is terminated by an end-of-line marker (a carriage-return / linefeed combination). Just think of Win.ini or Autoexec.bat. <B>Assign</B>
In order to start working with text files from Delphi we have to <I>link</I> a file on a disk to a file variable in our program. To create this link we must first declare a <B>variable</B> of type TextFile and then use <I>AssignFile</I> procedure in order to <I>associate</I> a file on a disk with a file variable.
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE>...
<B>var</B>
SomeTxtFile : TextFile;
<B>begin</B>
AssignFile(SomeTxtFile, FileName)
...
</PRE></TD><PRE></PRE></TR></TBODY></TABLE>Note: Unless the file named <I>FileName</I> is in the current directory, we need to provide enough information to identify its path. Be sure that value of a text variable has a <I>legal</I> Windows filename. <B>Reading information from a Text File</B>
If we want to read back the contest of a file into a string list, our task is easy. Just one line of code will do the job.
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE>...
Memo1.Lines.LoadFromFile('c:\autoexec.bat')
...
</PRE></TD><PRE></PRE></TR></TBODY></TABLE>On the other hand, to <B>read</B> information from a file line by line, we must open the file for input by using the <I>Reset</I> procedure. The <I>Reset</I> <B>opens</B> the <B>existing</B> file with the name assigned to TextFile variable. An error results if no existing external file of the given name exists. Once a file is reset, we can use <I>ReadLn</I> to read information from a file:
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE>...
<B>var</B>
SomeTxtFile : TextFile;
buffer : <B>string</B>;
<B>begin</B>
AssignFile(SomeTxtFile, 'c:\autoexec.bat');
Reset(SomeTxtFile);
ReadLn(SomeTxtFile, buffer);
Memo1.Lines.Add(buffer);
CloseFile(SomeTxtFile);
<B>end</B>;
...
</PRE></TD><PRE></PRE></TR></TBODY></TABLE>Procedure called <I>ReadLn</I>, reads one line of text from a file then moves to the next line. After adding one line of text from a file to a memo component <I>SomeTxtFile</I> needs to be closed. This is done by the <I>Close</I> keyword. Note: We can also use <I>Read</I> procedure to read information from a file. <I>Read</I> works just like <I>ReadLn</I>, except it does not move the pointer to the next line. As the next example shows, we can use multiple variables in each <I>Read</I> statement:
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE><B>var</B>
SomeTxtFile : TextFile;
buf1,buf2 : <B>string</B>[5];
<B>begin</B>
AssignFile(SomeTxtFile, 'c:\autoexec.bat');
Reset(SomeTxtFile);
ReadLn(SomeTxtFile, buf1,buf2);
ShowMessage(buf1 + ' ' +buf2);
CloseFile(SomeTxtFile);
<B>end</B>;
</PRE></TD><PRE></PRE></TR></TBODY></TABLE> <B>The EOF</B>
<I>Eof</I> is the <B>EndOfFile</B> checking function. We can use this function to make sure that we are not trying to read beyond the end of the file. Let's say we want to display the contest of the file in message boxes - one line at a time, until we get to the end of a file:
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE><B>var</B>
SomeTxtFile : TextFile;
buffer : <B>string</B>;
<B>begin</B>
AssignFile(SomeTxtFile, 'c:\autoexec.bat');
Reset(SomeTxtFile);
<B>while</B> <B>not</B> EOF(SomeTxtFile) <B>do</B> <B>begin</B>
ReadLn(SomeTxtFile, buffer);
ShowMessage(buffer);
<B>end</B>;
CloseFile(SomeTxtFile);
<B>end</B>;
</PRE></TD><PRE></PRE></TR></TBODY></TABLE>Note: It is better to use <I>While</I> loop (http://delphi.about.com/library/weekly/aa081099.htm) than an <I>Until </I>loop to take into account the (unlikely) possibility that the file exists but does not contain any data. <B>Sending information to a Text File</B>
<B>Writing</B> text to a file is as easy as reading text from a file. The <I>WriteLn</I> command is probably the most common way to <B>send</B> individual pieces of information to a file. The following code will <B>read</B> a text from a <I>Memo1</I> component (line by line) and <B>send</B> it to some <I>newly</I> created text file.
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE><B>var</B>
SomeTxtFile : TextFile;
i: integer;
<B>begin</B>
AssignFile(SomeTxtFile, 'c:\MyTextFile.txt');
Rewrite(SomeTxtFile);
<B>for</B> i := 0 <B>to</B> (Memo1.Lines.Count - 1) <B>do</B>
WriteLn(SomeTxtFile, Memo1.Lines[i]);
CloseFile(SomeTxtFile);
<B>end</B>;
</PRE></TD><PRE></PRE></TR></TBODY></TABLE>Depending on the state of the file provided to the <I>Rewrite</I> procedure in the previous example, the <I>Rewrite</I> creates a <B>new</B> file (opens the file for output) with the name assigned to <I>SomeTextFile</I>. If a file with the same name already exists, it is deleted and a new empty file is created in its place. If SomeTextFile is already open, it is first closed and then re-created. The current file position is set to the beginning of the empty file. Note: Memo1.Lines.SaveToFile('c:\MyTextFile.txt') will do the same. Sometimes we'll just need to <I>add some text data</I> to the end of an existing file. If this is the case, we'll call <I>Append</I> to ensure that a file is opened with write-only access with the file pointer positioned at the end of the file. Something like:
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE><B>var</B>
SomeTxtFile : TextFile;
<B>begin</B>
AssignFile(SomeTxtFile, 'c:\MyTextFile.txt');
Append(SomeTxtFile);
WriteLn(SomeTxtFile, 'New line in my text file');
CloseFile(SomeTxtFile);
<B>end</B>;
</PRE></TD><PRE></PRE></TR></TBODY></TABLE> <B>Be aware</B>
In general, you should always use exception handling (http://delphi.about.com/library/weekly/aa032399.htm) when working with files. I/O is full of surprises. Always use <I>CloseFile</I> in a <I>finally</I> block to avoid the possibility of corrupting a user's <I>FAT</I>. All the previous examples should be rewritten as follows:
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE><B>var</B>
SomeTxtFile : TextFile;
buffer : <B>string</B>;
<B>begin</B>
AssignFile(SomeTxtFile, 'c:\MyTextFile.txt');
<B>try</B>
Reset(SomeTxtFile);
ReadLn(SomeTxtFile, buffer);
<B>finally</B>
CloseFile(SomeTxtFile);
<B>end</B>;
<B>end</B>;
</PRE></TD><PRE></PRE></TR></TBODY></TABLE>To be sure that a given file exists we have to use <I>FileExists</I> boolean function. This function will return True if the file exists, Else otherwise. The syntax is
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE>function FileExists(const FileName: string): boolean
</PRE></TD><PRE></PRE></TR></TBODY></TABLE> (to be continued.
<TBODY>
<TR>
<TD colSpan=2>Creating flat (non-relational) databases with no database components <!-- End of Headline --></TD></TR>
<TR>
<TD bgColor=#cc0000 colSpan=2 height=1><IMG height=1 src="http://images.about.com/all/bullets/dot_clea.gif" width=1 border=0></TD></TR>
<TR>
<TD colSpan=2>Delphi Personal edition does not offer database support. In this chapter, you will find out how to create your own *flat* database and store any kind of data - all without a single data aware component. <!-- End of Subhead --></TD></TR>
<TR>
<TD colSpan=2><IMG height=6 src="http://images.about.com/all/bullets/dot_clea.gif" width=1></TD></TR></TBODY></TABLE>Welcome to the fifteenth chapter of the FREE online programming course:
<H5 style="PADDING-LEFT: 10px; MARGIN-BOTTOM: 0px; COLOR: #000080">No DB support in Delphi Personal edition</H5>As you probably know, Delphi Personal edition comes with no database support, in terms of data-aware components. Hopefully, "data world" isn't only about Paradox, Access, Interbase or MySQL.
The data your application needs to operate on may not always be stored in a relational database. It may be stored in an ASCII text file or a structured binary file. It may even be stored in an XML file. As you will learn from this chapter, your application can read data from a file (of *any* structure), update "fields", add new "records", and write data back to the file as if the data were stored in a *real* database. NOTE: flat-file databases are not as scaleable (and safe) as the relational model databases (MySQL, MS SQL Server, Interbase, etc). If you are only working with a small amount of data that is rarely updated then a flat-file database could be your choice.
However, if you are looking for a database for more frequent and heavy use then a relational database is probably more suitable.
Files from Delphi perspective:
Simply put a file is a binary sequence of some type. In Delphi, there a three classes of file: typed, text, and untyped. Typed files are files that contain data of a particular type, such as Double, Integer or previously defined custom Record type. Text files contain readable ASCII characters (organized into lines). Untyped files are used when we want to impose the least possible structure on a file.
<H5 style="PADDING-LEFT: 10px; MARGIN-BOTTOM: 0px; COLOR: #000080">Building your own database system</H5>The next series of articles shows you how to use Delphi to create a simple "database" application that interacts with data in text (ASCII) or binary files:
<H3>TEXT FILES IN DELPHI
Handling ASCII files from Object Pascal code.</H3> <B>The world isn't only about Paradox, Access, Interbase, MySQL, MS' SQL Server ...</B>
Simply put, <I>text files</I> contain readable ASCII characters. We can think of working with text file in Delphi as analogous to playing or recording information on a cassette tape.
Although it is possible to make changes within text file, jump around when processing information or add some data to the file other than at the end, it is advisable to use a text file only when we know that we are working with ordinary text and no such operations are necessary.
Text files are considered to represent a sequence of characters formatted into lines, where each line is terminated by an end-of-line marker (a carriage-return / linefeed combination). Just think of Win.ini or Autoexec.bat. <B>Assign</B>
In order to start working with text files from Delphi we have to <I>link</I> a file on a disk to a file variable in our program. To create this link we must first declare a <B>variable</B> of type TextFile and then use <I>AssignFile</I> procedure in order to <I>associate</I> a file on a disk with a file variable.
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE>...
<B>var</B>
SomeTxtFile : TextFile;
<B>begin</B>
AssignFile(SomeTxtFile, FileName)
...
</PRE></TD><PRE></PRE></TR></TBODY></TABLE>Note: Unless the file named <I>FileName</I> is in the current directory, we need to provide enough information to identify its path. Be sure that value of a text variable has a <I>legal</I> Windows filename. <B>Reading information from a Text File</B>
If we want to read back the contest of a file into a string list, our task is easy. Just one line of code will do the job.
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE>...
Memo1.Lines.LoadFromFile('c:\autoexec.bat')
...
</PRE></TD><PRE></PRE></TR></TBODY></TABLE>On the other hand, to <B>read</B> information from a file line by line, we must open the file for input by using the <I>Reset</I> procedure. The <I>Reset</I> <B>opens</B> the <B>existing</B> file with the name assigned to TextFile variable. An error results if no existing external file of the given name exists. Once a file is reset, we can use <I>ReadLn</I> to read information from a file:
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE>...
<B>var</B>
SomeTxtFile : TextFile;
buffer : <B>string</B>;
<B>begin</B>
AssignFile(SomeTxtFile, 'c:\autoexec.bat');
Reset(SomeTxtFile);
ReadLn(SomeTxtFile, buffer);
Memo1.Lines.Add(buffer);
CloseFile(SomeTxtFile);
<B>end</B>;
...
</PRE></TD><PRE></PRE></TR></TBODY></TABLE>Procedure called <I>ReadLn</I>, reads one line of text from a file then moves to the next line. After adding one line of text from a file to a memo component <I>SomeTxtFile</I> needs to be closed. This is done by the <I>Close</I> keyword. Note: We can also use <I>Read</I> procedure to read information from a file. <I>Read</I> works just like <I>ReadLn</I>, except it does not move the pointer to the next line. As the next example shows, we can use multiple variables in each <I>Read</I> statement:
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE><B>var</B>
SomeTxtFile : TextFile;
buf1,buf2 : <B>string</B>[5];
<B>begin</B>
AssignFile(SomeTxtFile, 'c:\autoexec.bat');
Reset(SomeTxtFile);
ReadLn(SomeTxtFile, buf1,buf2);
ShowMessage(buf1 + ' ' +buf2);
CloseFile(SomeTxtFile);
<B>end</B>;
</PRE></TD><PRE></PRE></TR></TBODY></TABLE> <B>The EOF</B>
<I>Eof</I> is the <B>EndOfFile</B> checking function. We can use this function to make sure that we are not trying to read beyond the end of the file. Let's say we want to display the contest of the file in message boxes - one line at a time, until we get to the end of a file:
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE><B>var</B>
SomeTxtFile : TextFile;
buffer : <B>string</B>;
<B>begin</B>
AssignFile(SomeTxtFile, 'c:\autoexec.bat');
Reset(SomeTxtFile);
<B>while</B> <B>not</B> EOF(SomeTxtFile) <B>do</B> <B>begin</B>
ReadLn(SomeTxtFile, buffer);
ShowMessage(buffer);
<B>end</B>;
CloseFile(SomeTxtFile);
<B>end</B>;
</PRE></TD><PRE></PRE></TR></TBODY></TABLE>Note: It is better to use <I>While</I> loop (http://delphi.about.com/library/weekly/aa081099.htm) than an <I>Until </I>loop to take into account the (unlikely) possibility that the file exists but does not contain any data. <B>Sending information to a Text File</B>
<B>Writing</B> text to a file is as easy as reading text from a file. The <I>WriteLn</I> command is probably the most common way to <B>send</B> individual pieces of information to a file. The following code will <B>read</B> a text from a <I>Memo1</I> component (line by line) and <B>send</B> it to some <I>newly</I> created text file.
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE><B>var</B>
SomeTxtFile : TextFile;
i: integer;
<B>begin</B>
AssignFile(SomeTxtFile, 'c:\MyTextFile.txt');
Rewrite(SomeTxtFile);
<B>for</B> i := 0 <B>to</B> (Memo1.Lines.Count - 1) <B>do</B>
WriteLn(SomeTxtFile, Memo1.Lines[i]);
CloseFile(SomeTxtFile);
<B>end</B>;
</PRE></TD><PRE></PRE></TR></TBODY></TABLE>Depending on the state of the file provided to the <I>Rewrite</I> procedure in the previous example, the <I>Rewrite</I> creates a <B>new</B> file (opens the file for output) with the name assigned to <I>SomeTextFile</I>. If a file with the same name already exists, it is deleted and a new empty file is created in its place. If SomeTextFile is already open, it is first closed and then re-created. The current file position is set to the beginning of the empty file. Note: Memo1.Lines.SaveToFile('c:\MyTextFile.txt') will do the same. Sometimes we'll just need to <I>add some text data</I> to the end of an existing file. If this is the case, we'll call <I>Append</I> to ensure that a file is opened with write-only access with the file pointer positioned at the end of the file. Something like:
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE><B>var</B>
SomeTxtFile : TextFile;
<B>begin</B>
AssignFile(SomeTxtFile, 'c:\MyTextFile.txt');
Append(SomeTxtFile);
WriteLn(SomeTxtFile, 'New line in my text file');
CloseFile(SomeTxtFile);
<B>end</B>;
</PRE></TD><PRE></PRE></TR></TBODY></TABLE> <B>Be aware</B>
In general, you should always use exception handling (http://delphi.about.com/library/weekly/aa032399.htm) when working with files. I/O is full of surprises. Always use <I>CloseFile</I> in a <I>finally</I> block to avoid the possibility of corrupting a user's <I>FAT</I>. All the previous examples should be rewritten as follows:
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE><B>var</B>
SomeTxtFile : TextFile;
buffer : <B>string</B>;
<B>begin</B>
AssignFile(SomeTxtFile, 'c:\MyTextFile.txt');
<B>try</B>
Reset(SomeTxtFile);
ReadLn(SomeTxtFile, buffer);
<B>finally</B>
CloseFile(SomeTxtFile);
<B>end</B>;
<B>end</B>;
</PRE></TD><PRE></PRE></TR></TBODY></TABLE>To be sure that a given file exists we have to use <I>FileExists</I> boolean function. This function will return True if the file exists, Else otherwise. The syntax is
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE>function FileExists(const FileName: string): boolean
</PRE></TD><PRE></PRE></TR></TBODY></TABLE> (to be continued.