public static String percentDecode ( final String input ) { if ( input . isEmpty ( ) ) { return input ; } try { final ByteArrayOutputStream bytes = new ByteArrayOutputStream ( ) ; int idx = 0 ; while ( idx < input . length ( ) ) { boolean isEOF = idx >= input . length ( ) ; int c = ( isEOF ) ? 0x00 : input . codePointAt ( idx ) ; while ( ! isEOF && c != ' ' ) { if ( c <= 0x7F ) { // String.getBytes is slow, so do not perform encoding // if not needed bytes . write ( ( byte ) c ) ; idx ++ ; } else { bytes . write ( new String ( Character . toChars ( c ) ) . getBytes ( UTF_8 ) ) ; idx += Character . charCount ( c ) ; } isEOF = idx >= input . length ( ) ; c = ( isEOF ) ? 0x00 : input . codePointAt ( idx ) ; } if ( c == ' ' && ( input . length ( ) <= idx + 2 || ! isASCIIHexDigit ( input . charAt ( idx + 1 ) ) || ! isASCIIHexDigit ( input . charAt ( idx + 2 ) ) ) ) { if ( c <= 0x7F ) { // String.getBytes is slow, so do not perform encoding // if not needed bytes . write ( ( byte ) c ) ; idx ++ ; } else { bytes . write ( new String ( Character . toChars ( c ) ) . getBytes ( UTF_8 ) ) ; idx += Character . charCount ( c ) ; } } else { while ( c == ' ' && input . length ( ) > idx + 2 && isASCIIHexDigit ( input . charAt ( idx + 1 ) ) && isASCIIHexDigit ( input . charAt ( idx + 2 ) ) ) { bytes . write ( hexToInt ( input . charAt ( idx + 1 ) , input . charAt ( idx + 2 ) ) ) ; idx += 3 ; c = ( input . length ( ) <= idx ) ? 0x00 : input . codePointAt ( idx ) ; } } } return new String ( bytes . toByteArray ( ) , UTF_8 ) ; } catch ( IOException ex ) { throw new RuntimeException ( ex ) ; } }
Percent - decodes a string .