ZnCharacterWriteStream — is it a WriteStream?

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

ZnCharacterWriteStream — is it a WriteStream?

Andrew Black-2
I’m making a stream to write on a file using

        outputFile := FileLocator home / 'Desktop' / classBeingTranslated name , '.grace'.
        outputFile writeStreamDo: [ :s |  ... ]

Is that OK?   When I do the above, in the writeStreamDo: block,  s is bound to an instance of  ZnCharacterWriteStream.    But that class does nt understand many methods from WriteStream.  For example, #contents is not understood, and nor is #ensureASpace.

To put things another way: I wrote tests using a stream created with String streamContents: [ :s | ... ], and everything worked fine.   Then, for production use, I switch to a stream created using outputFile writeStreamDo: [ :s | ... ] and everything breaks.

I know that ZnCharacterWriteStream is fairly new.  Am I doing something wrong, or is ZnCharacterWriteStream still under development?

        Andrew


Reply | Threaded
Open this post in threaded view
|

Re: ZnCharacterWriteStream — is it a WriteStream?

Richard O'Keefe
Without getting into a general debate about the new stream classes,
a stream class meant for writing to a file SHOULDN'T have #contents
in its interface.

(1) For example, if you open a channel for *output* in Unix, you have
no reason to expect that you have been granted a right to read it.
For example, suppose user=fred group=whizzy owns a file foo.grace
with permission bits rw--w---- and you are running a program as
user=mary group=whizzy.  You can open foo.grace for writing, but
you cannot read it.
(2) The thing you open might not be a file.  It might be, for
example, a symbolic link to /dev/null, a symbolic link to /dev/tty,
a named pipe, or even (in principle, I don't know if anyone has
done it, but with something like FUSE it *could* be done) a socket
to a remote machine.  In all these cases, *nobody* is storing the
contents.
(3) If the thing you open *is* a disc file, and you *do* have
permission to read it back, what should happen if you have written
more to the file than your memory can hold?

If you know that the output written to the stream is going to be
small enough that holding it in memory won't be a problem, could
you use a WriteStream and then write it to the output file in one
burst when it's finished?

Now, what about #ensureASpace?  It can *almost* be done on a
buffered stream by looking at the last character in the buffer
and adding a space if it isn't one.  But what if you called
#flush and the buffer is empty?  Well, in that case, if you have
a "monolithic" design where the stream records the last character
at every flush, it's still doable.  If you don't have a monolithic
design, you have to be able to read the last block before the
present one, and we've just seen why that is not in general
possible.  The one thing you can safely do is to say that if the
buffer is empty you will add a space just to be sure, so that the
contract for #ensureASpace becomes
   Ensures that the past contents of the receiver ends with a
   space.  Tries to avoid adding a space when there is already
   one, but may or may not succeed.


On 1 August 2018 at 10:34, Andrew P. Black <[hidden email]> wrote:
I’m making a stream to write on a file using

        outputFile := FileLocator home / 'Desktop' / classBeingTranslated name , '.grace'.
        outputFile writeStreamDo: [ :s |  ... ]

Is that OK?   When I do the above, in the writeStreamDo: block,  s is bound to an instance of  ZnCharacterWriteStream.    But that class does nt understand many methods from WriteStream.  For example, #contents is not understood, and nor is #ensureASpace.

To put things another way: I wrote tests using a stream created with String streamContents: [ :s | ... ], and everything worked fine.   Then, for production use, I switch to a stream created using outputFile writeStreamDo: [ :s | ... ] and everything breaks.

I know that ZnCharacterWriteStream is fairly new.  Am I doing something wrong, or is ZnCharacterWriteStream still under development?

        Andrew



Reply | Threaded
Open this post in threaded view
|

Re: ZnCharacterWriteStream — is it a WriteStream?

Sven Van Caekenberghe-2
In reply to this post by Andrew Black-2


> On 1 Aug 2018, at 00:34, Andrew P. Black <[hidden email]> wrote:
>
> I’m making a stream to write on a file using
>
> outputFile := FileLocator home / 'Desktop' / classBeingTranslated name , '.grace'.
> outputFile writeStreamDo: [ :s |  ... ]
>
> Is that OK?  

Yes

> When I do the above, in the writeStreamDo: block,  s is bound to an instance of  ZnCharacterWriteStream.    But that class does nt understand many methods from WriteStream.  For example, #contents is not understood, and nor is #ensureASpace.
>
> To put things another way: I wrote tests using a stream created with String streamContents: [ :s | ... ], and everything worked fine.   Then, for production use, I switch to a stream created using outputFile writeStreamDo: [ :s | ... ] and everything breaks.
>
> I know that ZnCharacterWriteStream is fairly new.  Am I doing something wrong, or is ZnCharacterWriteStream still under development?
>
> Andrew

The new streams are intentionally simpler, with a lighter API. If they were exactly the same, API wise, there would not be much point in doing them.