2

我有一个数据库中混合数据的案例,我想看看这是否是一个可以解决的问题。我拥有的是以下三种格式之一的部分 URL:

/some/path?ugly=häßlich // case 1, Encoding: UTF-8 (plain)
/some/path?ugly=h%C3%A4%C3%9Flich // case 2, Encoding: UTF-8 (URL-encoded)
/some/path?ugly=h%E4%DFlich // case 3: Encoding: ISO-8859-1 (URL-encoded)

我的应用程序中需要的是 URL 编码的 UTF8 版本

/some/path?ugly=h%C3%A4%C3%9Flich // Encoding: UTF-8 (URL-encoded)

数据库中的字符串都是 UTF-8,但 URL 编码可能存在也可能不存在,并且可能是任何一种格式。

我有一个a将纯 UTF-8 编码为 URL 编码的 UTF-8 的方法b,我有一个将 URL 编码的 ISO-8859-1 解码为纯 UTF-8 的方法,所以基本上我打算做的是:

情况1:

String output = a(input);

案例2:

String output = input;

案例3:

String output = a(b(input));

如果我知道哪个是哪个,所有这些情况都可以正常工作,但是我有没有一种安全的方法来检测这样的 String 是 case 2 还是 case 3?(我可以将参数中使用的语言限制为欧洲语言:德语、英语、法语、荷兰、波兰语、俄语、丹麦语、挪威语、瑞典语和土耳其语,如果有帮助的话)。

我知道显而易见的解决方案是清理数据,但不幸的是,数据不是我自己创建的,也没有必要的技术理解的人(并且有大量遗留数据需要处理)

4

3 回答 3

2

如果您可以假设仅对字母数字进行编码,则以下工作适用于:

  • “häßlich”
  • “h%C3%A4%C3%9Flich”
  • “h%E4%DFlich”

// 首先检查:

public static boolean isUtf8Encoded(String url) {
    return isAlphaNumeric(url);
}

public static boolean isUrlUtf8Encoded(String url)
        throws UnsupportedEncodingException {
    return isAlphaNumeric(URLDecoder.decode(url, "UTF-8"));
}

public static boolean isUrlIsoEncoded(String url)
        throws UnsupportedEncodingException {
    return isAlphaNumeric(URLDecoder.decode(url, "ISO-8859-1"));
}

private static boolean isAlphaNumeric(String decode) {
    for (char c : decode.toCharArray()) {
        if (!Character.isLetterOrDigit(c)) {
            return false;
        }
    }
    return true;
}
于 2012-07-10T20:33:34.760 回答
1

您可以在第一次解码然后编码时解决问题,如果您有未编码的 url 它不受解码的影响

 String url = "your url";
    url=URIUtil.decode(url, "UTF-8");
    url=URIUtil.encodeQuery(url, "UTF-8");
于 2016-10-12T12:27:46.373 回答
0

感谢接受的答案,但它不适用于 URL,因为 URL 还包含控制字符,这是我的解决方案:

/**
 * List of valid characters in URL.
 */
private static final List VALID_CHARACTERS = Arrays.asList(
        '-', '.', '_', '~', ':', '/', '?', '#', '[', ']', '@', '!',
        '$', '&', '\'', '(', ')', '*', '+', ',', ';', '='
);

/**
 * Check that decoding was successful or not.
 * @param url URL to check
 * @return True if it's valid.
 */
private static boolean isMalformed(final String url) {
    for (char c : url.toCharArray()) {
        if (VALID_CHARACTERS.indexOf(c) == -1 && !Character.isLetterOrDigit(c)) {
            return false;
        }
    }
    return true;
}

/**
 * Try to decode URL with specific encoding.
 * @param url URL
 * @param encoding Valid encoding
 * @return Decoded URL or null of encoding is not write
 * @throws java.io.UnsupportedEncodingException Throw if encoding does not support on your system.
 */
private static String _decodeUrl(final String url, final String encoding) {
    try {
        final String decoded = URLDecoder.decode(url, encoding);
        if(isMalformed(decoded)) {
            return decoded;
        }
    }
    catch (UnsupportedEncodingException ex) {
        throw new IllegalArgumentException("Illegal encoding: " + encoding);
    }
    return null;
}

/**
 * Decode URL with most popular encodings for URL.
 * @param url URL
 * @return Decoded URL or original one if encoding does not support.
 */
public static String decodeUrl(final String url) {
    final String[] mostPopularEncodings = new String[] {"iso-8859-1", "utf-8", "GB2312"};
    return decodeUrl(url, mostPopularEncodings);
}

/**
 * Decode URL with most popular encodings for URL.
 * @param url URL
 * @param encoding Encoding
 * @return Decoded URL or original one if encoding does not support.
 */
public static String decodeUrl(final String url, final String... encoding) {
    for(String e:encoding) {
        final String decoded;
        if((decoded = _decodeUrl(url, e)) != null) {
            return decoded;
        }
    }
    return url;
}
于 2014-06-24T05:09:18.483 回答