Java URLEncoder保留原始消息的大小写,但使UTF-8代码小写

问题描述 投票:0回答:3

我正在使用URLEncoder.encode(消息,“UTF-8”);编码一个字符串。

问题是我需要将最终字符串中的UTF-8代码设置为小写,同时保持原始消息的大小写。

例:

消息:{消息

期望输出:%5bMessage

URLEncoder.encode(“{Message”,“UTF-8”); - >%5BMessage

URLEncoder.encode(message,“UTF-8”)。toLowerCase(); - >%5bmessage

有没有办法改变URLEncoder的行为?

要么

对于所有UTF-8字符和任意字符串长度,是否有一种简单的方法可以将所有UTF-8代码转换为小写字母?

java utf-8 url-encoding case-sensitive
3个回答
0
投票

这是硬编码到URLEncoder(我正在看Oracle的JDK顺便说一句)。转换基本上转换您的角色,并获取每个角色的十六进制值,然后减去'a' -'A'(char值中的大写差异小写)之间的差异,以强制使用大写值。

if (Character.isLetter(ch)) {
    ch -= caseDiff;
}

我认为你可以解决这个问题的唯一方法是使用反射并将URLEncoder#caseDiff修改为0,因为这个变量是静态最终的:

static final int caseDiff = ('a' - 'A');

通过做类似的事情(考虑这个伪代码。你会想要第二次传递它):

try {
    Field declaredField = URLEncoder.class.getDeclaredField("caseDiff");
    Field modifiersField = Field.class.getDeclaredField("modifiers");

    modifiersField.setAccessible(true);
    modifiersField.setInt(declaredField, declaredField.getModifiers() & ~Modifier.FINAL);
    declaredField.setAccessible(true);
    declaredField.setInt(null, 0);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e1) {
    e1.printStackTrace();
}

我真的很好奇你打算这样做,我想知道这是不是你想要做的。


0
投票

问题是我需要将最终字符串中的UTF-8代码设置为小写,同时保持原始消息的大小写。

我认为你的意思是你希望URL转义中的十六进制数字用小写字母表示(这些不是“UTF-8代码”)。无论如何,这是一个令人讨厌的问题,因为URL编码(a.k.a。“百分比编码”)的规范明确指出百分比代码中的十六进制数字不区分大小写。仅在这些十六进制数字的情况下不同的两个百分比编码的URL是等效的,因此只要它在使用中,否则处理它们的代码可能是连续的问题。

有没有办法改变URLEncoder的行为?

The docs of java.net.URLEncoder非常简短。不需要太多的检查就可以看到没有,没有机制来调整其行为的这个方面。您可以编写自己的实现(并不难),或者您可能会找到第三方编码器,但标准库的编码器将无法满足您的要求。

对于所有UTF-8字符和任意字符串长度,是否有一种简单的方法可以将所有UTF-8代码转换为小写字母?

这取决于你所说的“简单”。原则上可以执行这样的转换,但是当您解析和更新编码的URL时,您花费的工作量至少是在您希望的方式执行编码所花费的两倍。第一名。

但如果你真的想这样做,那么你可能会使用这样的东西:

import java.util.regex.*;

public class URLRecoder {
    private final static Pattern CODE_PATTERN = Pattern.compile("%[0-9A-Fa-f]{2}");

    /**
     * Recodes a URL-encoded string to ensure that all hex digits in the
     * percent codes that are not decimal digits are expressed in lowercase.
     */
    public String recode(String urlString) {
        StringBuilder sb = new StringBuffer();
        Matcher m = CODER_PATTERN.matcher(urlString);

        while (m.find()) {
            m.appendReplacement(sb, m.group().toLowerCase());
        }
        m.appendTail(sb);

        return sb.toString();
    }
}

0
投票

我的解决方案是将URLEncoder源复制到一个新类中,并将hexStr常量从“0123456789ABCDEF”更改为“0123456789abcdef”。

由于可能的许可问题,不打算在此处发布代码:

/*===========================================================================
* Licensed Materials - Property of IBM
 * "Restricted Materials of IBM"
 * 
 * IBM SDK, Java(tm) Technology Edition, v8
 * (C) Copyright IBM Corp. 1995, 2013. All Rights Reserved
 *
 * US Government Users Restricted Rights - Use, duplication or disclosure
 * restricted by GSA ADP Schedule Contract with IBM Corp.
 *===========================================================================
 */
/*
 * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.`

源版本:

 * @version 1.31, 11/17/05
© www.soinside.com 2019 - 2024. All rights reserved.