Oponing a file twice

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Oponing a file twice

John Foster-3
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
Reply | Threaded
Open this post in threaded view
|

Re: Oponing a file twice

David T. Lewis
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
Reply | Threaded
Open this post in threaded view
|

Re: Opening a file twice

John Foster-3
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
Reply | Threaded
Open this post in threaded view
|

Re: Opening a file twice

Tapple Gao
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
Reply | Threaded
Open this post in threaded view
|

Re: Opening a file twice

Tapple Gao
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
Reply | Threaded
Open this post in threaded view
|

Re: Opening a file twice

David Mitchell-10
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