Exception Error on Return

Any ideas why the return true will create an exception. Puzzled!

if FileAndFolderVerify("HC Prefs Folder 2", "Menu Prefs") = true then TOS.WriteLine("97278888872") TOS. close end

Method:

[code]Var TOS As TextOutputStream

Var path As FolderItem = SpecialFolder.Desktop.Child (Folder)

If path.Exists = False Then path.CreateFolder

Var file As FolderItem = path.Child(FileName)

If Not file.Exists Then
TOS = TextOutputStream.Create(File) Rem Creates the file
End

If file.Exists then
Return True // False may or may not be here, compiler will tell you
else
Return False[/code]

What Exception do you get?

An exception of class NilObjectException was not handled. The application must shut down.

Writing to the Texoutputstream is what causes the error after the return true. If Boolean return is removed it works. Of course the if statement must also be remove to do this.

TOS.WriteLine(“97278888872”)
TOS. close

if FileAndFolderVerify("HC Prefs Folder 2", "Menu Prefs") = true then
  TOS.WriteLine("97278888872")
  TOS. close
end

In your calling code, you’re using a variable TOS, but that variable isn’t connected in any way to the function FileAndFolderVerify.

Var TOS As TextOutputStream

You do use a variable by the same name (TOS) in FileAndFolderVerify, but that is local to the function. I would recommend that you return TOS from the function instead of a boolean. And be sure to open the file whether it exists or not.

If Not file.Exists Then
  TOS = TextOutputStream.Create(File) Rem Creates the file
else
  TOS = TextOutputStream.Open(File)
End

I do have TOS set as a property Type TextOutputStream in the Class the methods are in.

But you are right Tim , opening the file again allows it to work.

I played with returning TOS as a TextOutputStream but it did not recognize it as one when returned so I went back to a property. I think it would have been more useful if it could be returned.

Have things settled down in Portland yet with the riots?

[quote=491012:@Clifford Coulter]I do have TOS set as a property Type TextOutputStream in the Class the methods are in.

But you are right Tim , opening the file again allows it to work.[/quote]
Ah, you have stumbled on a very common error. You have a local variable with the same name as a more global variable. Since the local variable is closer in scope, it gets used in the function, leaving the class property nil. Simply remove the line Var TOS As TextOutputStream from your FileAndFolderVerify function. That will make the function operate on the class property directly and cause your original code to work. As long as you open the file if it already exists.

The rioting has calmed enough that we don’t have a curfew imposed for tonight.

That should prove to be good knowledge for me. In my case removing Var TOS As TextOutputStream was not the answer since there was then no TOS to return. I was only trying to reduce duplication of code but it may not be worth it. Any way you parted some good info to me. Stay safe.

I don’t mean to belabor the point and I offer this purely as a learning opportunity. If your code is working, that’s awesome! No need to change it. There are a couple of ways to approach this.

  1. The way (I assume) you are doing it now. Use FileAndFolderVerify simply to create the file if it doesn’t exist.
Var file as FolderItem

if FileAndFolderVerify("HC Prefs Folder 2", "Menu Prefs") = true then
  file = SpecialFolder.Desktop.Child("HC Prefs Folder 2").Child("Menu Prefs")
  TOS = TextOutputStream.Open(file)
  TOS.WriteLine("97278888872")
  TOS. close
end
Function FileAndFolderVerify(Folder as String, FileName as String) as Boolean
  Var TOS As TextOutputStream

  Var path As FolderItem = SpecialFolder.Desktop.Child (Folder)

  If path.Exists = False Then path.CreateFolder

  Var file As FolderItem = path.Child(FileName)

  If Not file.Exists Then
    TOS = TextOutputStream.Create(File) Rem Creates the file
  End


  If file.Exists then
    Return True
  else
    Return False
  End
End Function

Note that Create will open the file as TOS, but since it is a local variable, it will go out of scope and be destroyed when the function ends, closing the file again. You then reopen it in the calling code.

  1. Use FileAndFolderVerify to open the file in the TOS class property.
if FileAndFolderVerify("HC Prefs Folder 2", "Menu Prefs") = true then
  TOS.WriteLine("97278888872")
  TOS. close
end
Function FileAndFolderVerify(Folder as String, FileName as String) as Boolean
  Var path As FolderItem = SpecialFolder.Desktop.Child (Folder)

  If path.Exists = False Then path.CreateFolder

  Var file As FolderItem = path.Child(FileName)

  If Not file.Exists Then
    TOS = TextOutputStream.Create(File) Rem Creates the file
  else
    TOS = TextOutputStream.Open(File)
  End


  If file.Exists then
    Return True 
  else
    Return False
  End
End Function
  1. A little more advanced. Have FileAndFolderVerify return the TextOutputStream.
Var TOS as TextOutputStream

TOS = FileAndFolderVerify("HC Prefs Folder 2", "Menu Prefs")
if TOS <> Nil then
  TOS.WriteLine("97278888872")
  TOS. close
end
Function FileAndFolderVerify(Folder as String, FileName as String) as TextOutputStream
  Var TOS As TextOutputStream

  Var path As FolderItem = SpecialFolder.Desktop.Child (Folder)

  If path.Exists = False Then path.CreateFolder

  Var file As FolderItem = path.Child(FileName)

  If Not file.Exists Then
    TOS = TextOutputStream.Create(File) Rem Creates the file
  else
    TOS = TextOutputStream.Open(File)
  End

  Return TOS
End Function

Note that this code doesn’t use the class property at all. One valid reason to use the class property would be if you wanted to write to the file in multiple functions. In that case, use option #2. Otherwise, it would be preferable to dispense with the class property and just use local variables.

I have spent some time studying sub-functions in RB Definitive Guide but have not figured out in the code editor where to place subs or functions. I have not used any in the past. It looks like a good idea for me to understand how. Can you give me a little guidance? I have poked around for hours on this. RB Definitive Guide says in the method handlers. But ???

Sure. Functions and Subroutines are both called Methods in Xojo. The only difference is one has a return type and the other leaves that field blank. When you add a Method, there are 3 major fields to fill out: Name, Parameters, Return Type. So for something like

Function FileAndFolderVerify(Folder as String, FileName as String) as Boolean

You would enter
Name: FileAndFolderVerify
Parameters: Folder as String, FileName as String
Return type: Boolean

The actual code (everything between Function and End Function) goes in the code editor window. You have obviously done this already when you created your FileAndFolderVerify function, but might not have put the 2 concepts together.

Talk about casing my tail all day. Nothing more then a method with a return and prams which I always use. So it looks like I need to place only the code you suggested between the functions. %%^*()(&^(^DAMM

I wanted to try your #3 example but I get the error on Return TOS.
Type mismatch error. Expected Boolean, but got class TextOutputStream

Did you change the return type to TextOutputStream?

I did but have anothe error t figure out: Window1.FileAndFolderVerify, line 1
Syntax error
FileAndFolderVerify(Folder as String, FileName as String) as TextOutputStream

Do not include Function and End Function in the code editor. That’s the textual form. You parcel them out into the Method’s fields and only include the code in between them in the code editor.

You meant the whole line I believe not just word function. Silly me.

And example three works with no error. Your patience and knowledge is more then appreciated Tim to get me restarted.