Just as I was thinking I was getting a handle on this I'm terribly
confused... a _ FileStream fileNamed: 'readme.txt'. gives me a stream an the file. b _ FileStream fileNamed: 'readme.txt'. gives me nil a _ nil. a _ FileStream fileNamed: 'readme.txt'. a is still nil It seems that the only way I can reopen this file is to Smalltalk garbageCollect. Now if I simply wanted to have two references to the file I could just b _ a copy. But what if I open a stream on a file, then reuse my variable, then sometime later want to use that file again? Do I have to explicitly perform garbage collection? That seems very wrong. Do I have to keep a hold of all references to files and their filenames if I think I _might_ need that file again? That also seems very wrong. Scenario: ... some code a _ FileStream fileNamed: 'readme.txt'. some more code ... a _ result of something ... even more code b _ FileStream fileNamed: 'readme.txt'. I've looked at FileStream, StandardFileStream and MultiByteFileStream for 2 days now and am none the wiser (not quite true, I've learned you can send Squeak into lala land by putting 'self halt' inside FileStream>>fileNamed: and then getting any error at all... the debugger seems to open a stream that opens a debugger that opens a stream that opens a debugger etc etc) What am I missing (I assume I'm overlooking something really simple)? Thanks, John _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
Hi John,
On Thu, Jul 05, 2007 at 10:53:14PM +1000, [hidden email] wrote: > Just as I was thinking I was getting a handle on this I'm terribly > confused... > > a _ FileStream fileNamed: 'readme.txt'. > > gives me a stream an the file. > > b _ FileStream fileNamed: 'readme.txt'. > > gives me nil This is because you have tried to open two file streams on the same file, and you are using Windows. The nil result just means that the file open failed the second time because Windows will not let you open the file twice. If you had closed the first file stream ("a close"), then the second one would have succeeded, and your b variable would have pointed to a file stream. > a _ nil. > a _ FileStream fileNamed: 'readme.txt'. > > a is still nil This is because that first file stream (the one that used to be associated with your "a" variable) still exists. It has not yet been garbage collected, and it also is still connected to an open Windows file. Therefore the operating system will still refuse to let you open the file a second time. > It seems that the only way I can reopen this file is to > > Smalltalk garbageCollect. This cleans up that "orphaned" instance of the file stream. It just so happens that file streams are set up with a finalization method that is automatically invoked as the instance is being collected, and the finalization method closes the open Windows file handle. This is meant as a safety net to protect against the sort of programming error in which someone opens a file, but forgets to close it properly. Without the finalization method, file handles could accumulated indefinitely, eventually causing problems (the actual effect of this will vary from one operating system to another). > Now if I simply wanted to have two references to the file I could just > > b _ a copy. > > But what if I open a stream on a file, then reuse my variable, then > sometime later want to use that file again? Do I have to explicitly > perform garbage collection? That seems very wrong. Do I have to keep a > hold of all references to files and their filenames if I think I _might_ > need that file again? That also seems very wrong. Just keep track of one actual object that refers to the open file. Don't make copies of it, and do remember to close it when you a finished using the file. If you need to reuse your variable, assign the file stream object to some other variable so you don't lose track of it. > Scenario: > > ... > some code > a _ FileStream fileNamed: 'readme.txt'. > some more code > ... > a _ result of something > ... > even more code > b _ FileStream fileNamed: 'readme.txt'. > > I've looked at FileStream, StandardFileStream and MultiByteFileStream for > 2 days now and am none the wiser (not quite true, I've learned you can > send Squeak into lala land by putting 'self halt' inside > FileStream>>fileNamed: and then getting any error at all... the debugger > seems to open a stream that opens a debugger that opens a stream that > opens a debugger etc etc) > > What am I missing (I assume I'm overlooking something really simple)? You probably would be better off to not use the "a" variable for two different purposes. It's also a good idea to use longer, more descriptive variable names. Possibly something more like this: readmeFile := FileStream fileNamed: 'readme.txt'. Then don't use that variable for anything other than refering to the readme file stream. Then later on, do something like this: readmeFile ifNotNilDo: [readmeFile close]. (Note: I'm using ":=" rather than "_" for assigning to a variable. Either one will work, but in the last couple of years, folks have been moving to the convention of using ":=" instead of "_"). As a side note, there is a method called #ensure: that can be used to ensure that a file gets closed even if things go wrong in your code. This should probably be the topic of a separate discussion, but the basic idea is to write something like this: readmeFile := FileStream fileNamed: 'readme.txt'. [ "Do stuff with readmeFile here" ] ensure: [readmeFile ifNotNil: [readmeFile close]]. Or another way to write this is: (FileStream fileNamed: 'readme.txt') ifNotNilDo: [:readmeFile | [ "Do stuff with readmeFile here" ] ensure: [readmeFile close]]. HTH, Dave _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
Thanks Dave.
I'd looked at #close, but already had the system in a pretty weird state so it didn't seem to help. #ensure: is the kind of thing I really needed - but never found. Two more questions arise: 1) How do I get a password to edit the wiki? The page 'Recipe: Reading a file' could use a note about this. 2) When I had things really borked I did a 'Explore it' on 'FileStream allInstances' and saw a few entries that had all the fields set to nil except fileID, which was the same value as a valid stream on the file. In Windows or unix I can close a file if all I have is the file descriptor(/handle). How would I close the file if I've broken all the references, apart from forcing a garbage collect? > Hi John, <snip> > (Note: I'm using ":=" rather than "_" for assigning to a variable. > Either one will work, but in the last couple of years, folks have > been moving to the convention of using ":=" instead of "_"). > '_' is very convenient on a Dvorak keyboard. > HTH, > Dave _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
On Fri, Jul 06, 2007 at 09:23:40AM +1000, [hidden email] wrote:
> Thanks Dave. > > I'd looked at #close, but already had the system in a pretty weird state > so it didn't seem to help. > > #ensure: is the kind of thing I really needed - but never found. It is a method on a block: BlockContext>>ensure: BlockClosure>>ensure: you can use World Menu -> open -> Method Finder to find methods > Two more questions arise: > > 1) How do I get a password to edit the wiki? The page 'Recipe: Reading a > file' could use a note about this. username: squeak password: viewpoints > 2) When I had things really borked I did a 'Explore it' on 'FileStream > allInstances' and saw a few entries that had all the fields set to nil > except fileID, which was the same value as a valid stream on the file. In > Windows or unix I can close a file if all I have is the file > descriptor(/handle). How would I close the file if I've broken all the > references, apart from forcing a garbage collect? FileStream allInstances do: [ :each | each close ] -- Matthew Fulmer -- http://mtfulmer.wordpress.com/ Help improve Squeak Documentation: http://wiki.squeak.org/squeak/808 _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
On Thu, Jul 05, 2007 at 04:47:15PM -0700, Matthew Fulmer wrote:
> > 2) When I had things really borked I did a 'Explore it' on 'FileStream > > allInstances' and saw a few entries that had all the fields set to nil > > except fileID, which was the same value as a valid stream on the file. In > > Windows or unix I can close a file if all I have is the file > > descriptor(/handle). How would I close the file if I've broken all the > > references, apart from forcing a garbage collect? > > FileStream allInstances do: [ :each | each close ] you could also be selective about it: - Type "FileStream allInstances" - hit cmd-shift-I (this runs the "explore it" command) - select the file you want to close - type "self close" in the code panel of the explorer - hit cmd-D ("do it") but doing "Smalltalk garbageCollect" is fine too -- Matthew Fulmer -- http://mtfulmer.wordpress.com/ Help improve Squeak Documentation: http://wiki.squeak.org/squeak/808 _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
In reply to this post by John Foster-3
re: wiki password. Search the mail archives I think it is:
user:squeak password: viewpoints _______________________________________________ Beginners mailing list [hidden email] http://lists.squeakfoundation.org/mailman/listinfo/beginners |
Free forum by Nabble | Edit this page |