Iâm a Xojo beginner so bear with me if I ask stupid questions along the way I have managed to make an app for Raspberry that has different properties updated by a timer.
For example if the MainPump is active the timer will +1 every second to the property MainPumpCounter.
I have four properties stored as integers:
MainPumpCounter
VibrationCounter
SpaCounter
MachineTimeCounter
However I have ran against the wall when trying to add two event handlers to the app.
Eventhandler1)
When the program is closed I would like it to save the properties to a textfile in a folder on the desktop called Miberi
The textfile I would like to be named MachineProperties
In the file should then be stored the four properties
If the file already exits it should be overwritten (the .create function as far as I understand)
This process Iâm trying to do without the showdialog (the program should do it in the background without user envolvement)
Eventhandler2)
When the program is opened I would like the program to read the text file (if it exits) and overwrite the current value of the four properties
I hope your bright minds can help me on this puzzle as I have spend hours googling and reading the forums + xojo docs but canât seem to put the puzzle together on how to get it to work
Eventhandler1 would be the close/closing event of your application and look something like
Var t As TextOutputStream = TextOutputStream.Create(SpecialFolder.Desktop.Child("MachineProperties"))
t.WriteLine(MachineTimeCounter.ToString)
t.WriteLine(MainPumpCounter.ToString)
t.WriteLine(SpaCounter.ToString)
t.WriteLine(VibrationCounter.ToString)
t.Close
EventHandler2 would be the open/opening event of your app and look something like
Var f As FolderItem = SpecialFolder.Desktop.Child("MachineProperties")
If f.Exists Then
Var t As TextInputStream = TextInputStream.Open(f)
MachineTimeCounter = t.ReadLine.ToInteger
MainPumpCounter = t.ReadLine.ToInteger
SpaCounter = t.ReadLine.ToInteger
VibrationCounter = t.ReadLine.ToInteger
t.Close
End If
The order that you write/read your properties doesnât matter so long as they are the same.
I didnât check for Nil as this is a desktop project and I canât conceive of a situation where specialfolder.desktop doesnât exist without the OS being corrupt. If the file were in a folder on the desktop then yes that may be useful.
I can do it without corrupting the OS (and did it years ago on some of my computers).
In the Finder, select your desktop folder (from your Home folder), get info and remove all permissions (read, write and execute).
SpecialFolder.Desktop would still exist, thatâs not the problem. Accessing anything in it would return nil.
The OP did mention that the file would be in a folder on the desktop. So I would amend Wayneâs code as
var f as FolderItem = SpecialFolder.Desktop.Child("Miberi")
if f <> Nil and f.Exists then f = f.Child("MachineProperties")
if f <> Nil then
Var t As TextOutputStream = TextOutputStream.Create(f)
t.WriteLine(MachineTimeCounter.ToString)
t.WriteLine(MainPumpCounter.ToString)
t.WriteLine(SpaCounter.ToString)
t.WriteLine(VibrationCounter.ToString)
t.Close
End
var f as FolderItem = SpecialFolder.Desktop.Child("Miberi")
if f <> Nil and f.Exists then f = f.Child("MachineProperties")
if f <> Nil and f.Exists then
Var t As TextInputStream = TextInputStream.Open(f)
MachineTimeCounter = t.ReadLine.ToInteger
MainPumpCounter = t.ReadLine.ToInteger
SpaCounter = t.ReadLine.ToInteger
VibrationCounter = t.ReadLine.ToInteger
t.Close
End
Somewhat more advanced but worth considering is using JSON or XML for your properties file (still text, so file operations are the same). This will make your properties file self-explanatory since each property will have a human-readable key identifying what it is. It also makes the read/write order unimportant, so you can never screw it up by unthinkingly changing the order, since each property will be accessed by its key rather than its position in the file.
If youâve only got four properties itâs probably not a big deal but if your app grows, the benefits will increase.
@Tim_Hare I got it working with the help of your code so thank you very much
What do you mean with â+1 on key/value pairs in the file formatâ?
Sorry but I donât understand
I was agreeing with Juliaâs comment. If you ever start to add more fields to the file, you should consider some format where each value is labeled. It makes it a lot more flexible and easier to read if you need to inspect the file in a text editor.
Hello
I have the suggested code from Tim Hare running, but sometimes (seem to random when) I get an error crashing the program:
An exception of class NilObjectException was not handled. The application must be shut down.
When clicking ok (which is the only option) the program closes.
I have read about exception handling in Xojo docs and done a lot of googling but canât figure out a way to catch the exception and then simply delete (and/or) ignore it and let the program continue.
Where is the exception occurring? Run the app under the debugger and ensure that in the Project menu you have Break on Exceptions set. Then see where the exception occurs. Thatâs the first step. Then post back here with the code around the exception line.
I will give it a try but my problem is that there can go a week or two without any exceptions. Thatâs why Iâm trying to figure out if it is possible to simple catch the exception and then ignore it without showing a messageboxâŠ
The code I have when the app opens:
var f as FolderItem = SpecialFolder.Desktop.Child(âAHTpropertiesâ)
if f <> Nil and f.Exists then f = f.Child(âAHTcountersâ)
if f <> Nil and f.Exists then
Var t As TextInputStream = TextInputStream.Open(f)
App.TĂŠllerMaskineIgang = t.ReadLine.ToInteger
App.TÊllerLÞbebÄnd = t.ReadLine.ToInteger
App.TĂŠllerVibration = t.ReadLine.ToInteger
App.TĂŠllerHovedpumpe = t.ReadLine.ToInteger
App.TĂŠllerSandfilterStdTank = t.ReadLine.ToInteger
App.TĂŠllerSandfilterKoldTank = t.ReadLine.ToInteger
App.TĂŠllerSolarie = t.ReadLine.ToInteger
App.TĂŠllerSpa = t.ReadLine.ToInteger
App.TĂŠllerFintFilter = t.ReadLine.ToInteger
App.TĂŠllerGrovFilter = t.ReadLine.ToInteger
t.Close
End
The code I have when the app closes:
var f as FolderItem = SpecialFolder.Desktop.Child(âAHTpropertiesâ)
if f <> Nil and f.Exists then f = f.Child(âAHTcountersâ)
if f <> Nil then
Var t As TextOutputStream = TextOutputStream.Create(f)
t.WriteLine(App.TĂŠllerMaskineIgang.ToString)
t.WriteLine(App.TÊllerLÞbebÄnd.ToString)
t.WriteLine(App.TĂŠllerVibration.ToString)
t.WriteLine(App.TĂŠllerHovedpumpe.ToString)
t.WriteLine(App.TĂŠllerSandfilterStdTank.ToString)
t.WriteLine(App.TĂŠllerSandfilterKoldTank.ToString)
t.WriteLine(App.TĂŠllerSolarie.ToString)
t.WriteLine(App.TĂŠllerSpa.ToString)
t.WriteLine(App.TĂŠllerFintFilter.ToString)
t.WriteLine(App.TĂŠllerGrovFilter.ToString)
t.Close
End
have you edit this file maybe? (just because any byte order mark at the beginning (BOM))
do not recycle variables
use one for the path the other for the file.
if the path not exists create it. https://documentation.xojo.com/api/files/folderitem.html.CreateFolder
it is not necessary to test nil if you got a object.
The file AHTcounters has not been edited and I have checked that permissions for folder and file are set to anyone⊠I know with certainty that the folder AHTproperties exist as it is created on the Desktop in advance manually when I set up the piâŠ
I have the debugger running now, so Iâm just hoping it will not take weeks for this error to occur.
My problem is though that I have been through all xojo documentation and searched hours on google without any luck.
When the nilobjectexception occours I would like to ignore it and let the app continue. Iâm simply a beginner so I canât figure out how to do that as all examples are with âshow messageboxâ instead off âignore exceptionâ
on error resume is not good.
first you need the method where the nilobject exception happens.
as example here
Var t As TextOutputStream
you access this t direct
if open fails you got no stream
t would be nil
t.ReadLine fail, would be nil.Readline
you can use app wide error handling here (not for resume next, just to know why and where)
You can catch exceptions to handle them and prevent the application from failing and exiting. However, you have to know where they are. Have you seen the NilObjectException in debug? Do you know whereabouts it could be happening?
App.UnhandledException should be a last resort and not your go-to resolution. Do not implement this event and return true simply to avoid this one issue.
If you donât know where the NilObjectException is occurring, you could wrap your whole routine in a tryâŠcatch and that would still be a more appropriately scoped solution than App.UnhandledException.
try
var f as FolderItem = SpecialFolder.Desktop.Child(âAHTpropertiesâ)
if f <> Nil and f.Exists then f = f.Child(âAHTcountersâ)
if f <> Nil then
Var t As TextOutputStream = TextOutputStream.Create(f)
t.WriteLine(App.TĂŠllerMaskineIgang.ToString)
t.WriteLine(App.TÊllerLÞbebÄnd.ToString)
t.WriteLine(App.TĂŠllerVibration.ToString)
t.WriteLine(App.TĂŠllerHovedpumpe.ToString)
t.WriteLine(App.TĂŠllerSandfilterStdTank.ToString)
t.WriteLine(App.TĂŠllerSandfilterKoldTank.ToString)
t.WriteLine(App.TĂŠllerSolarie.ToString)
t.WriteLine(App.TĂŠllerSpa.ToString)
t.WriteLine(App.TĂŠllerFintFilter.ToString)
t.WriteLine(App.TĂŠllerGrovFilter.ToString)
t.Close
End
catch ex as NilObjectException
// Something went terribly wrong, the data was not saved.
end try