tags:

views:

307

answers:

2

MyWriter.java (execute this before MyReader.java)

import java.io.*;
import java.net.*;
import java.util.* ;

public class MyWriter {

    public static void main(String[] args) throws Exception {

     ServerSocket ss = new ServerSocket(1234) ;
     System.out.println("Server started...\n\n") ;
     Socket s = ss.accept() ;

     OutputStream out = s.getOutputStream() ;

     Scanner scan = new Scanner(System.in) ;

     while(true){
      System.out.print("Enter integer (or something else to quit) : ");

      try{
       int i = scan.nextInt() ;
       out.write(i) ;
      }catch(RuntimeException rte){
       System.out.println("\n\n") ;
       rte.printStackTrace() ;
       System.out.println("\n\n") ;
       break ;
      }
     }
    }
}

MyReader.java (only executed, when done with MyWriter.java)

import java.io.*;
import java.net.*;
import java.util.* ;

public class MyReader {

    public static void main(String[] args) throws Exception {

     Socket s = new Socket("localhost", 1234) ;

     InputStream is = s.getInputStream() ;

     int i ;
     while( (i = is.read()) != -1 ){
      System.out.println( "character form : " + (char)i + ", int form : " + i);
     }
    }
}

Problem : MyReader is not getting terminated, even if I am passing -1 in MyWriter.

+2  A: 

Read returns an int so that it can also indicate the end of the stream, as -1. If the signature were

byte read()

then you'd never know when the stream had ended (unless it threw an exception, I suppose).

I suspect there's no particular reason for write to take an int - it seems a slightly strange choice to me. The Javadoc specifically says that the higher 24 bits are ignored. Maybe this is just an accident of history.

(In .NET, Stream.ReadByte returns an int, but Stream.WriteByte takes a byte. This makes more sense IMO.)

Now, with that background, when you write "-1" to your stream, you're actually writing the value "255" - and that's what you read back. "-1" is represented in binary as "all 1s" so the lower 8 bits of that are "11111111" which is 255 when considered as an unsigned value.

Your reader will only terminate when you close the output stream in the "writing" application - because that's when read() will return -1.

Jon Skeet
then why here MyReader is not getting terminated for -1 input.
rits
I was editing to explain that.
Jon Skeet
thnx Mr. Skeet :)
rits
I got this from Java RMI by William Grosso :-The fact that the argument to the basic write( ) method isan integer is somewhat peculiar. Recall that read( )returned an integer, rather than a byte, in order to allowinstances of InputStream to signal exceptional conditions.write( ) takes an integer, rather than a byte, so that theread and write method declarations are parallel. In otherwords, if you've read a value in from a stream, and it's not -1,you should be able to write it out to another stream withoutcasting it.
rits
Hmm. I'd argue that that's an edge case and not worth bending the API out of shape for. It means that *every implementation of OutputStream* has to do the cast instead, effectively... *and* the signature doesn't reflect the meaning. Bad decision IMO.
Jon Skeet
A: 

The best way of figuring out what is wrong with the code is to debug it, besides looking at the java doc.

In this case the read method will not return -1 unless it reaches the end of the stream, the values that are returned by the method are between 0 and 255 otherwise.

This is the Java Doc of the method:

/**
 * Reads the next byte of data from the input stream. The value byte is
 * returned as an <code>int</code> in the range <code>0</code> to
 * <code>255</code>. If no byte is available because the end of the stream
 * has been reached, the value <code>-1</code> is returned. This method
 * blocks until input data is available, the end of the stream is detected,
 * or an exception is thrown.
 *
 * <p> A subclass must provide an implementation of this method.
 *
 * @return     the next byte of data, or <code>-1</code> if the end of the
 *             stream is reached.
 * @exception  IOException  if an I/O error occurs.
 */

I have rewritten the class in order to facilitate debugging:

import java.io.InputStream; import java.net.Socket;

public class MyReader {

public static void main(String[] args) throws Exception {
    Socket s = new Socket("localhost", 1234);
    InputStream is = s.getInputStream();

    int i;
    do {
        i = is.read();
        System.out.println("character form : " + (char) i + ", int form : " + i);
    } while (i != -1);
}

}

have fun ;)

dr_hoppa