Why doesn't this work anymore?

I’m playing with some code I modified to save my serial port preferences. I have used this code before. If there is no folder and it gets to the line “If prefFolder <> Nil then” it will continue and give a IOException 2. When I examined the preFolder value, it says Nil.

What’s going on?

Var prefFolder As FolderItem

#If DebugBuild Then

prefFolder = SpecialFolder.Desktop.Child(“Pbo3pText”)

#Else

prefFolder = SpecialFolder.ApplicationData.Child(“Pbo3pText”)

#Endif

If prefFolder <> Nil then

Var prefFile As FolderItem = prefFolder.Child(“Pbo3pText.json”)

Var tis As TextInputStream tis = TextInputStream.Open(prefFile)

Var prefs As JSONItem prefs = New JSONItem(tis.ReadAll) tis.Close

SerialPortTesterName = prefs.Value(“SerialPortTester”)

SerialPortGeneratorName = prefs.Value(“SerialPortGenerator”)

End If

make sure your folder exists and is readable. not only if it’s <> Nil.
You can read the .Message of the IOException by using

Try

you code here

Catch e As IOException
messagebox "IOException " + e.message

Catch e As JSONException
messagebox "JSONException" + e.message

Catch e As NilObjectException
messagebox "NilObjectException" + e.message

End Try
1 Like

If you’re going to post code, please check what you post. Then highlight it with the mouse and press the </> button. When I just copies/pasted your posted code and compiled it, I got about 8 errors right off. Posting it properly avoids the errors with the wrong quotes and other formatting problems.

1 Like

I think what the OP is saying is that his code executes the

If prefFolder <> Nil then

block even though when he examines prefFolder it’s Nil. Which doesn’t sound possible…

That’s to be expected since the exception is catched.

Um, no, if PrefFolder is Nil then no IO operations should be performed and there should be no IOException.

Var prefFolder As FolderItem

#If DebugBuild Then
prefFolder = SpecialFolder.Desktop.Child(“Pbo3pText”)
#Else
prefFolder = SpecialFolder.ApplicationData.Child(“Pbo3pText”)
#Endif

If prefFolder <> Nil then

Var prefFile As FolderItem = prefFolder.Child(“Pbo3pText.json”)
Var tis As TextInputStream tis = TextInputStream.Open(prefFile)
Var prefs As JSONItem prefs = New JSONItem(tis.ReadAll) tis.Close
SerialPortTesterName = prefs.Value(“SerialPortTester”)
SerialPortGeneratorName = prefs.Value(“SerialPortGenerator”)

End If

Hmmm.

Var prefFolder As FolderItem

#If DebugBuild Then
  prefFolder = SpecialFolder.Desktop.Child("Pbo3pText")
#Else
  prefFolder = SpecialFolder.ApplicationData.Child("Pbo3pText")
#Endif

If prefFolder <> Nil then

  Var prefFile As FolderItem = prefFolder.Child("Pbo3pText.json")
  Var tis As TextInputStream
  tis = TextInputStream.Open(prefFile)
  Var prefs As JSONItem
  prefs = New JSONItem(tis.ReadAll)
  tis.Close
  SerialPortTesterName = prefs.Value("SerialPortTester")
  SerialPortGeneratorName = prefs.Value("SerialPortGenerator")

End If

There is indeed no Try/Catch, so an exception, if any, will not be caught.

If he reads an IOException with number 2 it must have came from somewhere right?
So this could be the debugger giving the wrong information (line indicator) but still there is an exception. If break on exceptions is on it will be shown anyway.

No try catch but the debugger will stil show any exception.

Even if it was a build he would have seen “This application has an uncaught BLahExeception” unless he handles App.UnhandledException differently.

Right, but the OP said

He doesn’t tell us where he was breakpointed, but if prefFolder was indeed Nil on entry to the If-Then block it obviously couldn’t have been executed and no IOException could have occurred, so something isn’t adding up.

@Donald_Porada maybe the file is not in the actual location anymore?

If the file is blocked by Windows Defender or MacOS Folder Preferences (privacy and security) this could very well be what he sees.

Maybe he has another property “preFolder” (as he wrote) and that was Nil, but prefFolder (in code) was not Nil :slight_smile:

1 Like

Yes, I thought of mentioning this, but I think in most of those situations the item is not Nil, but it is nonexistent as far as the app is concerned. OP doesn’t say what OS he is on.

Oh but if the app is quarantined I bet this is exactly what would happen…

2 Likes

Thanks for all of the feedback. I’m not sure where I got the code from originally, but the way it used to work (I’ve used it for years) is that it would try to load the preferences, and if it couldn’t find the file, it would load defaults. When the save preferences was executed, a file was created if there wasn’t one.

Julie Truchsess: The code stops at "tis = TextInputStream.Open(preFile)

Does this help anybody?

Well it should help you. Scroll down and look at the value of prefFile. What is it? You seem to have an exception. WHat is its message property?

OK, we can assume that prefFolder is not Nil, since it exists and we got into the If-Then block.

What about prefFile? Does it exist?

If this is the first time the app is running in debug mode maybe prefFile doesn’t exist.

1 Like

OK, you need to slow down. This is over my head. I’m more of an embedded programmer.

I have very little experience in file I/O, so that’s why I have been reusing this code.

From my understanding of the code, the first time it runs, it tries to load the file Pbo3pText.json. If it doesn’t find it, it skips over the Open. The information says that it doesn’t exist. Please explain to an inexperienced xojo programmer what is actually going on. Sorry for my ignorance.
Here is the screenshot of the full prefFile window.

Your prefFile does simply not exist.
So you have to check if it exists, before you try to open it in a textinputstream, and if not handle the situation: create a new empty prefFile, copy a prefilled file from the resource folder or stop executing your app…

Have to distinguish between prefFile (a folderitem) and the file it points to (or may point to). Because you’ve used .Child when trying to create the folderitem, it can be Nil (according to the docs), and so you should be testing for Nil before proceeding to the next step. Now, you have:

If prefFolder <> Nil then

  Var prefFile As FolderItem = prefFolder.Child("Pbo3pText.json")
  Var tis As TextInputStream
  tis = TextInputStream.Open(prefFile)

but you don’t check that prefFile is not Nil before trying the .Open. There is no code there to skip over the Open if the file does not exist. So you should have:

 Var prefFile As FolderItem = prefFolder.Child("Pbo3pText.json")
if  (prefFile<>Nil and prefFile.Exists=True)  then
 Var tis As TextInputStream
  tis = TextInputStream.Open(prefFile)
  // etc

Personally I code these things the other way around (I also put all the declarations at the top so they don’t clutter up the code), thus:

If  (prefFolder=Nil)  then
  // report the error here
  Return
end if

prefFile = prefFolder.Child("Pbo3pText.json")
if  (prefFile=Nil or prefFile.Exists=False or prefFile.IsReadable=False)  then
  // Report this error here
  Return
end if

tis = TextInputStream.Open(prefFile)
prefs = New JSONItem(tis.ReadAll)
tis.Close
SerialPortTesterName = prefs.Value("SerialPortTester")
SerialPortGeneratorName = prefs.Value("SerialPortGenerator")

Tidy logic is the key to clarity in the code, and for being sure that all cases that can occur are catered for. As it stands you’re not doing enough checvking, not reporting possible errors, and so the code can run and at its end you have no idea what it did or didn’t do.