javainputstreamoutputstreamdatainputstreamdataoutputstream

Input/OutputStream between System.in and System.out - problem with readUTF() and writeUTF()


I'm trying to set up a very simple communication flow between System.in and System.out in Java, in order to understand how streams work. I'm using DataInputStream for System.in and DataOutputStream for System.out, and they're communicating through readChar(), writeChar() and all.

Everything seems to work fine, until readUTF() is reached:

DataInputStream dis = new DataInputStream(System.in);
DataOutputStream dos = new DataOutputStream(System.out);
        
try {
  char c = dis.readChar();
  dos.writeChar(c);
            
  int i = dis.readInt();
  dos.writeInt(i);
            
  String s = dis.readUTF();
  dos.writeUTF(s);
} catch (IOException e) {
  e.printStackTrace();
}       
try {
  dis.close();
  dos.close();
} catch (IOException e) {
  e.printStackTrace();
}   

Console is displaying:

m /* note: keyboard input */
m
569
569
Hello

Looks like I can't find the way to indicate the end of the String, return isn't taken into account, nor \n etc. I've tried adding " too but same.

And I got a problem the other way around to, this code isn't displaying anything in the console:

DataInputStream dis = new DataInputStream(System.in);
DataOutputStream dos = new DataOutputStream(System.out);
        
try {
  dos.writeUTF("Hello");
} catch (IOException e) {
  e.printStackTrace();
}       
try {
  dis.close();
  dos.close();
} catch (IOException e) {
 e.printStackTrace();
}

I've tried adding dos.flush() but nothing changes. I think I'm misunderstanding something.


Solution

  • You shouldn't be using DataInputStream and DataOutputStream. The readUTF and writeUTF use a very specific serialization format, where the text is prefixed with a length indicator, and using modified UTF8. Console input doesn't use such format, so the first 4 characters of Hello are used to calculate the length, and you haven't input that many characters, and on output the 4 bytes used for the length of the string will likely generate garbage (as will the use of the modified UTF8, if you include codepoints that generate a modified format). You should probably use a BufferedReader or Scanner instead and use the PrintStream System.out directly, or use a Console obtained through System.console().