On 1/29/11 5:30 PM, Steven Bethard wrote:
On Fri, Jan 28, 2011 at 2:48 PM, Jörn Kottmann<[email protected]>  wrote:
On 1/28/11 11:06 AM, Steven Bethard wrote:
Again, I'm not asking for Iterators*instead of*  whatever custom
protocol you want to design. I'm asking for them*in addition to*  your
protocol.
[snip]
// The created Iterator also implements Iterable
ObjectStreamUtils.toIterator(ObjectStream)
Sure, I guess you could make it a static method, though I don't see
why you couldn't just add the method to AbstractEventStream (or
whatever the equivalent for ObjectStreams is).

I do not want to be annoying here, but I really have a strong impression
that all most everybody who will use the ObjectStream as a java.util.Iterator
will write code which does not do the error handling correctly. For
experienced programmers it is confusing when they read such code,
because they will believe that error handling and closing is not necessary with
an Iterator.

For all that we gain a little convienence that it is possible to use a for-each loop
instead of a while loop.

Here's what I would
really like to write:

InputStream in = new FileInputStream("your-file.train);
PlainTextByLineStream stream = new PlainTextByLineStream(in, "UTF-8")
for (String line: stream) {
     ...
}
stream.close();

This would appear in the body of a function declared as "throws
IOException" since I can't do anything useful if the IO fails here.
But see below for how someone who wants to handle such exceptions
could.


Ok, lets change your sample a bit, and lets say it should count the lines
in the input file.

int countLines(File file) throws IOException {
  int counter = 0;
InputStream in = new FileInputStream("your-file.train); // here it could throw IOException

  try {
PlainTextByLineStream stream = new PlainTextByLineStream(in, "UTF-8") // might throw IOException
    for (String line: stream) {
      counter++;
    }
  }
  finally {
    in.close();
  }

  return counter;
}

Now we have someone who calls this method, there both
exceptions must be handled, IOException and RuntimeIOException.
RuntimeIOException could be ignored, and might as well will in most
cases because people might think that handling an IOException
when working with the disk is enough.

You might want to solve this by also catching the first IOException and
turn it into a RuntimeIOException, which adds a few lines to the above sample.

How do you want to get around the exception handling
the java IO interface forces you to do ?
You mean, how do I implement iterator() when read() throws an
IOException? Here's the code:

public abstract class AbstractObjectStream<T>  implements
ObjectStream<T>, Iterable<T>  {
   public Iterator<T>  iterator() {
     return new Iterator<T>() {

       private T next = this.readNext();

       @Override
       public boolean hasNext() {
         return this.next != null;
       }

       @Override
       public T next() {
         T result = this.next;
         this.next = this.readNext();
         return result;
       }

       @Override
       public void remove() {
         throw new UnsupportedOperationException();
       }

       private T readNext() {
         try {
           return read(); // calling ObjectStream.read() here
         } catch (IOException e) {
           throw new RuntimeIOException(e);
         }
       }
     };
   }
}

That's it. Now just have PlainTextByLineStream subclass
AbstractObjectStream and the earlier code snippet will work perfectly.

I believe that then ObjectStream should extend the Iterable.
Would you bother to close the stream ? Or do you do not
want to do this also ?
The iterator shouldn't close the stream. That's the responsibility of
whoever opened in the IO stream. In the code sample above, you can see
that I close the PlainTextByLineStream at the end of the code snippet.


That responsibility can only be taken if try-finally or later
when java 7 is out, try-with-resources is used.
In the end you somehow have to handle the IOExceptions, thats
just how the Java API is made.
Sure. See above. Or perhaps you meant, how would a user who wanted to
use the Iterator API and also wanted to handle the IOExceptions write
the code? Well, I'd contend that a user who is working with this kind
of low level detail probably wants to use the ObjectStream API.
(Remember, we're talking about both APIs being available at the same
time, so you can choose whichever is most appropriate).

Here I have a completely different opinion, handling the IO errors
is not a "low level detail" only some users should care doing. And
I also think that you are better of using ObjectStreams directly if
error handling should be done. Which leads me again to my
impression that adding that features will not do any good to the
user code which calls our API.

Why would it make sense for us to add a feature which leads to buggy
user code?

Jörn

Reply via email to