Here you can find the source of percentDecode(String str, boolean plusToSpace)
Decodes strings that have been <a href="http://tools.ietf.org/html/rfc3986#section-2.1">percent encoded</a>.
Parameter | Description |
---|---|
str | the input string to decode |
plusToSpace | true if the plus sign ("+") should be converted to a single space (" ") |
public static String percentDecode(String str, boolean plusToSpace)
//package com.java2s; /* Copyright (C) 2013-2014 Ian Teune <ian.teune@gmail.com> * //from w w w . j a v a 2s . com * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ public class Main { private static final byte[] BYTES = new byte[16]; /** * Same as * {@link #percentDecode(String, boolean) percentDecode(str, false)}. */ public static String percentDecode(String str) { return percentDecode(str, false); } /** * Decodes strings that have been * <a href="http://tools.ietf.org/html/rfc3986#section-2.1">percent * encoded</a>. Decoding is always performed using {@code UTF-8} (there is * currently no way of changing this). * <p> * Invalid percent encoded sequences or sequences that represent invalid * {@code UTF-8} will cause an {@code IllegalArgumentException} to be * thrown. The only exception to this are * <a href="http://en.wikipedia.org/wiki/UTF-8#Overlong_encodings">overlong * encodings</a>, which are permitted and will be decoded correctly. * <p> * This method is very similar to * {@link java.net.URLDecoder#decode(String, String) URLDecoder.decode(...)}, * but differs in the following ways: * <ul> * <li>Decoding <i>always</i> uses {@code UTF-8}, whereas {@code URLDecoder} * allows any encoding.</li> * <li>The plus ("+") character is converted to a space (" ") <i>only</i> * if {@code plusToSpace} is true, whereas {@code URLDecoder} always * converts a plus into a space.</li> * <li>For heavily percent encoded input, this method will likely perform * better than {@code URLDecoder} as this method directly decodes the * {@code UTF-8}.</li> * </ul> * * @param str the input string to decode * @param plusToSpace true if the plus sign ("+") should be converted to a * single space (" ") * @return the decoded string. If no changes need to be made to {@code str}, * it will be returned as is. */ public static String percentDecode(String str, boolean plusToSpace) { char[] buf = null; int count = 0; //current index in buf final int len = str.length(); for (int i = 0; i < len;) { char c = str.charAt(i); if (c == '%') { if (i + 2 >= len) { throw new IllegalArgumentException(); } if (buf == null) { buf = new char[len]; str.getChars(0, i, buf, 0); count = i; } int b = (toDigit(str.charAt(i + 1)) << 4) | toDigit(str.charAt(i + 2)); i += 3; if (b > 0x7F) { int bytes = BYTES[(b >> 3) & 0x0F]; if (bytes == 0) { throw new IllegalArgumentException(); } assert bytes >= 2 : bytes; b &= (0x80 >> bytes) - 1; b <<= (bytes - 1) * 6; for (bytes--; bytes > 0; bytes--) { if (i + 2 >= len || str.charAt(i) != '%') { throw new IllegalArgumentException(); } int n = (toDigit(str.charAt(i + 1)) << 4) | toDigit(str.charAt(i + 2)); if ((n & 0xC0) != 0x80) { throw new IllegalArgumentException(); } b |= (n & 0x3F) << ((bytes - 1) * 6); i += 3; } } count += Character.toChars(b, buf, count); } else { if (c == '+' && plusToSpace) { if (buf == null) { buf = new char[len]; str.getChars(0, i, buf, 0); count = i; } buf[count++] = ' '; } else if (buf != null) { buf[count++] = c; } i++; } } return buf != null ? new String(buf, 0, count) : str; } private static int toDigit(int c) { if (c > '9') { if (c > 'F') { if (c >= 'a' && c <= 'f') { return c - 'a' + 10; } } else if (c >= 'A') { return c - 'A' + 10; } } else if (c >= '0') { return c - '0'; } throw new IllegalArgumentException(); } }