You are still assuming the length in bytes in UTF-8 matches the length of chars in UTF-16. Consider this case:

  new URIish("ssh://user@host/åpath%2Estring")

This is a valid input. The å cannot be represented as a single byte in UTF-8, its a two-byte value. I think this loop will fail horribly on this input and not produce a reasonable result.

I think we would prefer this loop to convert the bare å into its URL encoded version of its UTF-8 form, thus "cleaning up the input". If its not going to do that, we need to throw a URISyntaxException and refuse the input. But right now I think this method will mangle the input because the position of the % in the byte array is not the same position as the % in the String object, so you will try to perform parseInt against non-hex text.