public final static String readUTF(DataInput in) throws IOException
public final String readUTF() throws IOException
  public final static String readUTF(DataInput in) throws IOException  {    final int UTFlen = in.readUnsignedShort();    byte[] buf = new byte[UTFlen];    StringBuffer strbuf = new StringBuffer();    // This blocks until the entire string is available rather than    // doing partial processing on the bytes that are available and then    // blocking.  An advantage of the latter is that Exceptions    // could be thrown earlier.  The former is a bit cleaner.    in.readFully(buf, 0, UTFlen);    for (int i = 0; i < UTFlen; )      {	if ((buf[i] & 0x80) == 0)		// bit pattern 0xxxxxxx	  strbuf.append((char) (buf[i++] & 0xFF));	else if ((buf[i] & 0xE0) == 0xC0)	// bit pattern 110xxxxx	  {	    if (i + 1 >= UTFlen || (buf[i+1] & 0xC0) != 0x80)	      throw new UTFDataFormatException();	    strbuf.append((char) (((buf[i++] & 0x1F) << 6) |				  (buf[i++] & 0x3F)));	  }	else if ((buf[i] & 0xF0) == 0xE0)	// bit pattern 1110xxxx	  {	    if (i + 2 >= UTFlen ||		(buf[i+1] & 0xC0) != 0x80 || (buf[i+2] & 0xC0) != 0x80)	      throw new UTFDataFormatException();	    strbuf.append((char) (((buf[i++] & 0x0F) << 12) |				  ((buf[i++] & 0x3F) << 6) |				  (buf[i++] & 0x3F)));	  }	else // must be ((buf[i] & 0xF0) == 0xF0 || (buf[i] & 0xC0) == 0x80)	  throw new UTFDataFormatException();	// bit patterns 1111xxxx or						// 		10xxxxxx      }    return strbuf.toString();  }