public static String readToken(InputStream in, int delim,
            String enc, int maxLength) throws IOException {
        // note: we avoid using a ByteArrayOutputStream here because it
        // suffers the overhead of synchronization for each byte written
        int buflen = maxLength < 512 ? maxLength : 512; // start with less
        byte[] buf = new byte[buflen];
        int count = 0;
        int c;
        while ((c = in.read()) != -1 && c != delim) {
            if (count == buflen) { // expand buffer
                if (count == maxLength)
                    throw new IOException("token too large (" + count + ")");
                buflen = maxLength < 2 * buflen ? maxLength : 2 * buflen;
                byte[] expanded = new byte[buflen];
                System.arraycopy(buf, 0, expanded, 0, count);
                buf = expanded;
            }
            buf[count++] = (byte)c;
        }        
        if (c == -1 && delim != -1)
            throw new IOException("unexpected end of stream");
        return new String(buf, 0, count, enc);
    }