Many applications use text files to store textual data, store user settings or many other usages.
It is pretty simple to work with text files, but still there are some points that you should be aware of.
The default encoding for text files is UTF8. This allows you to read or write any Unicode character.
You could choose to use ASCII encoding instead. ASCII encoding supports only the lower values of the ASCII table (0-127).
Note that UTF8 encoded files will start with a special Unicode marking.
Most applications recognize this marking and do not show it.
However, some older applications will show something like ";fe" at the beginning of the text. In such cases use ASCII encoding instead.
If you write a DOS batch file (on the desktop) then you should use ASCII encoding for that reason.
As an example we will create a small application with some user data. The user data will be loaded when the application starts (Sub App_Start) and saved when the application ends (Sub Form1_Close).
The source code file and the settings file are attached to the post.
Saving code:
File operations could fail, if for example the file is used by another application.
We are using ErrorLabel to handle unexpected errors and show a message to the user.
Now for the real part...
First we open the file with FileOpen.
The first parameter is the name that we give to this connection.
The second parameter is the path and file name.
In this case the file is located in the same folder of the source code (or compiled executable).
The third parameter could be cRead, cWrite or cRandom.
Text files should be opened for reading (cRead) or writing (cWrite), only binary files should use cRandom.
When using cWrite or cRandom, FileOpen will create a new file if it doesn't exist.
Text files are usually written one line after another and reading is done in a similar way.
FileWrite writes a string to the file, each string in a new line.
FileWrite receives two parameters, the connection name and the value to write.
Using FileWrite we store the form's data to the file.
As we've done writing we now close the connection with FileClose.
Only one connection could be made to a file, so it is important to close the connection when it is no longer required.
Now for the reading...
Again we handle unexpected errors with ErrorLabel.
First we check if the file exists. If it doesn't exist we exit this sub using Return.
A new reading connection is created using FileOpen and cRead flag.
We could have used 'c1' instead of 'c2' as the connection name (c2 is used to prevent confusion between the two parts).
The settings file is built of several known fields and an unknown number of fields as the ListBox items.
FileRead reads a single line from the connection.
Each time the next line will be read.
In the same order we previously saved the data, we now read the first three known lines.
The remaining data is now fetched and a new item is added to the ListBox for each line.
Each line is compared to the EOF constant which symbols the End Of File.
When the value equals to EOF we know that there are no more items left.
Another approach would have been to write the number of items before the items.
FileReadToEnd reads the entire remaining data (unlike FileRead which only reads the next single line).
Handling binary files could be done with FileGet and FilePut and with the BinaryFile library.
It is pretty simple to work with text files, but still there are some points that you should be aware of.
The default encoding for text files is UTF8. This allows you to read or write any Unicode character.
You could choose to use ASCII encoding instead. ASCII encoding supports only the lower values of the ASCII table (0-127).
Note that UTF8 encoded files will start with a special Unicode marking.
Most applications recognize this marking and do not show it.
However, some older applications will show something like ";fe" at the beginning of the text. In such cases use ASCII encoding instead.
If you write a DOS batch file (on the desktop) then you should use ASCII encoding for that reason.
As an example we will create a small application with some user data. The user data will be loaded when the application starts (Sub App_Start) and saved when the application ends (Sub Form1_Close).
The source code file and the settings file are attached to the post.
Saving code:
B4X:
[SIZE=2][COLOR=#0000ff]Sub [/COLOR][/SIZE][SIZE=2]SaveINI
[/SIZE][SIZE=2][COLOR=#0000ff] ErrorLabel[/COLOR][/SIZE][SIZE=2](errSaveINI)
[/SIZE][SIZE=2][COLOR=#0000ff] FileOpen[/COLOR][/SIZE][SIZE=2]( c1,[/SIZE][SIZE=2][COLOR=#800000]"TextFiles.ini"[/COLOR][/SIZE][SIZE=2],cWrite)
[/SIZE][SIZE=2][COLOR=#0000ff] FileWrite[/COLOR][/SIZE][SIZE=2](c1,txtFirstName.Text)
[/SIZE][SIZE=2][COLOR=#0000ff] FileWrite[/COLOR][/SIZE][SIZE=2](c1,txtLastName.Text)
[/SIZE][SIZE=2][COLOR=#0000ff] FileWrite[/COLOR][/SIZE][SIZE=2](c1,chkValidAccount.Checked) [/SIZE][SIZE=2][COLOR=#008000]'writing a boolean value.
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff] For[/COLOR][/SIZE][SIZE=2] i = [/SIZE][SIZE=2][COLOR=#800080]0[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]To[/COLOR][/SIZE][SIZE=2] lstData.Count-[/SIZE][SIZE=2][COLOR=#800080]1
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff] FileWrite[/COLOR][/SIZE][SIZE=2](c1,lstData.Item(i))
[/SIZE][SIZE=2][COLOR=#0000ff] Next
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff] FileClose[/COLOR][/SIZE][SIZE=2](c1)
[/SIZE][SIZE=2][COLOR=#0000ff] Return[/COLOR][/SIZE][SIZE=2][COLOR=#008000]'If there were no "Return" here, the error message would have shown.
[/COLOR][/SIZE][SIZE=2] errSaveINI:
[/SIZE][SIZE=2][COLOR=#0000ff] Msgbox[/COLOR][/SIZE][SIZE=2]([/SIZE][SIZE=2][COLOR=#800000]"Error writing INI file."[/COLOR][/SIZE][SIZE=2],[/SIZE][SIZE=2][COLOR=#800000]""[/COLOR][/SIZE][SIZE=2],cMsgboxOK,cMsgboxHand)
[/SIZE][SIZE=2][COLOR=#0000ff] FileClose[/COLOR][/SIZE][SIZE=2](c1)[/SIZE]
[SIZE=2][COLOR=#0000ff]End Sub
[/COLOR][/SIZE]
We are using ErrorLabel to handle unexpected errors and show a message to the user.
Now for the real part...
First we open the file with FileOpen.
The first parameter is the name that we give to this connection.
The second parameter is the path and file name.
In this case the file is located in the same folder of the source code (or compiled executable).
The third parameter could be cRead, cWrite or cRandom.
Text files should be opened for reading (cRead) or writing (cWrite), only binary files should use cRandom.
When using cWrite or cRandom, FileOpen will create a new file if it doesn't exist.
Text files are usually written one line after another and reading is done in a similar way.
FileWrite writes a string to the file, each string in a new line.
FileWrite receives two parameters, the connection name and the value to write.
Using FileWrite we store the form's data to the file.
As we've done writing we now close the connection with FileClose.
Only one connection could be made to a file, so it is important to close the connection when it is no longer required.
Now for the reading...
B4X:
[FONT=Courier New][SIZE=2][COLOR=#0000ff]Sub [/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2]LoadINI[/SIZE][/FONT]
[FONT=Courier New][SIZE=2][COLOR=#0000ff] ErrorLabel[/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2](errLoadINI)[/SIZE][/FONT]
[FONT=Courier New][SIZE=2][COLOR=#0000ff] If [/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2][COLOR=#0000ff]Not[/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2]([/SIZE][/FONT][FONT=Courier New][SIZE=2][COLOR=#0000ff]FileExist[/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2]([/SIZE][/FONT][FONT=Courier New][SIZE=2][COLOR=#800000]"TextFiles.ini"[/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2])) [/SIZE][/FONT][FONT=Courier New][SIZE=2][COLOR=#0000ff]Then [/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2][COLOR=#0000ff]Return[/COLOR][/SIZE][/FONT]
[FONT=Courier New][SIZE=2][COLOR=#0000ff] FileOpen[/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2](c2,[/SIZE][/FONT][FONT=Courier New][SIZE=2][COLOR=#800000]"TextFiles.ini"[/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2],cRead)[/SIZE][/FONT]
[SIZE=2][FONT=Courier New] txtFirstName.Text = [/FONT][/SIZE][FONT=Courier New][SIZE=2][COLOR=#0000ff]FileRead[/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2](c2)[/SIZE][/FONT]
[SIZE=2][FONT=Courier New] txtLastName.Text = [/FONT][/SIZE][FONT=Courier New][SIZE=2][COLOR=#0000ff]FileRead[/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2](c2)[/SIZE][/FONT]
[SIZE=2][FONT=Courier New] chkValidAccount.Checked = [/FONT][/SIZE][FONT=Courier New][SIZE=2][COLOR=#0000ff]FileRead[/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2](c2)[/SIZE][/FONT]
[SIZE=2][FONT=Courier New] s = [/FONT][/SIZE][FONT=Courier New][SIZE=2][COLOR=#0000ff]FileRead[/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2](c2)[/SIZE][/FONT]
[FONT=Courier New][SIZE=2][COLOR=#0000ff] Do[/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2][COLOR=#0000ff]Until[/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2] s = EOF [/SIZE][/FONT][FONT=Courier New][SIZE=2][COLOR=#008000]'Read the ListBox items.[/COLOR][/SIZE][/FONT]
[FONT=Courier New][SIZE=2] lstData.Add(s)[/SIZE][/FONT]
[SIZE=2][FONT=Courier New] s = [/FONT][/SIZE][FONT=Courier New][SIZE=2][COLOR=#0000ff]FileRead[/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2](c2)[/SIZE][/FONT]
[FONT=Courier New][SIZE=2][COLOR=#0000ff] Loop[/COLOR][/SIZE][/FONT]
[FONT=Courier New][SIZE=2][COLOR=#0000ff] FileClose[/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2](c2)[/SIZE][/FONT]
[FONT=Courier New][SIZE=2][COLOR=#0000ff] Return[/COLOR][/SIZE][/FONT]
[FONT=Courier New][SIZE=2] errLoadINI:[/SIZE][/FONT]
[FONT=Courier New][SIZE=2][COLOR=#0000ff] Msgbox[/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2]([/SIZE][/FONT][FONT=Courier New][SIZE=2][COLOR=#800000]"Error reading INI file."[/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2],[/SIZE][/FONT][FONT=Courier New][SIZE=2][COLOR=#800000]""[/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2],cMsgboxOK,cMsgboxHand)[/SIZE][/FONT]
[FONT=Courier New][SIZE=2][COLOR=#0000ff] FileClose[/COLOR][/SIZE][/FONT][FONT=Courier New][SIZE=2](c2)[/SIZE][/FONT]
[FONT=Courier New][SIZE=2][COLOR=#0000ff]End Sub[/COLOR][/SIZE][/FONT]
First we check if the file exists. If it doesn't exist we exit this sub using Return.
A new reading connection is created using FileOpen and cRead flag.
We could have used 'c1' instead of 'c2' as the connection name (c2 is used to prevent confusion between the two parts).
The settings file is built of several known fields and an unknown number of fields as the ListBox items.
FileRead reads a single line from the connection.
Each time the next line will be read.
In the same order we previously saved the data, we now read the first three known lines.
The remaining data is now fetched and a new item is added to the ListBox for each line.
Each line is compared to the EOF constant which symbols the End Of File.
When the value equals to EOF we know that there are no more items left.
Another approach would have been to write the number of items before the items.
FileReadToEnd reads the entire remaining data (unlike FileRead which only reads the next single line).
Handling binary files could be done with FileGet and FilePut and with the BinaryFile library.