如何让Java匹配JavaScript encodeURIComponent()方法?

mat*_*ith 4 javascript java url encoding utf-8

我试图在包含特殊字符的URL中传递此字符串,并且我能使其工作的唯一方法是使用JavaScript encodeURIComponent('testerๆ8ๅ'),它产生" 测试者%C3%A6%C3%B8%C3 %A5 "

我在Java中尝试做的所有事情都会产生不同的编码,并且不能在另一端工作......任何想法我怎么能在Java中将测试人员ๆ8ๅ编码为测试人员%C3%A6%C3%B8%C3%A5?提前致谢!

package com.mastercard.cp.sdng.domain.user;

import org.apache.commons.lang.StringUtils;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;

public class UrlEncodingSample
{
    public static void main(String[] args)
    {
        String userId = "dummy";
        try
        {
            validateEncoding(userId);

            userId = "testeræøå";

            validateEncoding(userId);

            userId = URLEncoder.encode(userId);

            validateEncoding(userId);
        }
        catch (UnsupportedEncodingException e)
        {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }

    }

    private static void validateEncoding(String userId) throws UnsupportedEncodingException
    {
        System.out.println("------ START TESTING WITH USER ID = '"+userId+"' ----------------------");
        System.out.println("Test URLEncoder.encode(userId): " + URLEncoder.encode(userId));
        System.out.println("Test URLEncoder.encode(userId,\"UTF-8\"): " + URLEncoder.encode(userId, "UTF-8"));
        System.out.println("Test URLEncoder.encode(userId,\"UTF-16\"): " + URLEncoder.encode(userId,"UTF-16"));
        System.out.println("Test URLEncoder.encode(userId,\"UTF-16LE\"): " + URLEncoder.encode(userId,"UTF-16LE"));
        System.out.println("Test URLEncoder.encode(userId,\"UTF-16BE\"): " + URLEncoder.encode(userId,"UTF-16BE"));

        ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
        try
        {
            System.out.println("Test engine.eval(\"encodeURIComponent(\\\"\"+userId+\"\\\")\"): " +
                    engine.eval("encodeURIComponent(\""+userId+"\")"));
        }
        catch (ScriptException e)
        {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        System.out.println("Test encodeURIComponent(userId): " + encodeURIComponent(userId));
        try
        {
            System.out.println("TEST new URI(userId).toASCIIString(): " + new URI(userId).toASCIIString());
        }
        catch (URISyntaxException e)
        {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        System.out.println("------ END TESTING WITH USER ID = '"+userId+"' ----------------------\n\n");

    }



    public static String encodeURIComponent(String input) {
        if(StringUtils.isEmpty(input)) {
            return input;
        }

        int l = input.length();
        StringBuilder o = new StringBuilder(l * 3);
        try {
            for (int i = 0; i < l; i++) {
                String e = input.substring(i, i + 1);
                if (ALLOWED_CHARS.indexOf(e) == -1) {
                    byte[] b = e.getBytes("utf-8");
                    o.append(getHex(b));
                    continue;
                }
                o.append(e);
            }
            return o.toString();
        } catch(UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return input;
    }

    private static String getHex(byte buf[]) {
        StringBuilder o = new StringBuilder(buf.length * 3);
        for (int i = 0; i < buf.length; i++) {
            int n = (int) buf[i] & 0xff;
            o.append("%");
            if (n < 0x10) {
                o.append("0");
            }
            o.append(Long.toString(n, 16).toUpperCase());
        }
        return o.toString();
    }

    public static final String ALLOWED_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'()";
}
Run Code Online (Sandbox Code Playgroud)

上述类的输出是这样的:


    ------ START TESTING WITH USER ID = 'dummy' ----------------------
    Test URLEncoder.encode(userId): dummy
    Test URLEncoder.encode(userId,"UTF-8"): dummy
    Test URLEncoder.encode(userId,"UTF-16"): dummy
    Test URLEncoder.encode(userId,"UTF-16LE"): dummy
    Test URLEncoder.encode(userId,"UTF-16BE"): dummy
    Test engine.eval("encodeURIComponent(\""+userId+"\")"): dummy
    Test encodeURIComponent(userId): dummy
    TEST new URI(userId).toASCIIString(): dummy
    ------ END TESTING WITH USER ID = 'dummy' ----------------------


    ------ START TESTING WITH USER ID = 'tester???' ----------------------
    Test URLEncoder.encode(userId): tester%E6%F8%E5
    Test URLEncoder.encode(userId,"UTF-8"): tester%E0%B9%86%E0%B9%98%E0%B9%85
    Test URLEncoder.encode(userId,"UTF-16"): tester%FE%FF%0E%46%0E%58%0E%45
    Test URLEncoder.encode(userId,"UTF-16LE"): tester%46%0E%58%0E%45%0E
    Test URLEncoder.encode(userId,"UTF-16BE"): tester%0E%46%0E%58%0E%45
    Test engine.eval("encodeURIComponent(\""+userId+"\")"): tester%e0%b9%86%e0%b9%98%e0%b9%85
    Test encodeURIComponent(userId): tester%E0%B9%86%E0%B9%98%E0%B9%85
    TEST new URI(userId).toASCIIString(): tester%E0%B9%86%E0%B9%98%E0%B9%85
    ------ END TESTING WITH USER ID = 'tester???' ----------------------


    ------ START TESTING WITH USER ID = 'tester%E6%F8%E5' ----------------------
    Test URLEncoder.encode(userId): tester%25E6%25F8%25E5
    Test URLEncoder.encode(userId,"UTF-8"): tester%25E6%25F8%25E5
    Test URLEncoder.encode(userId,"UTF-16"): tester%FE%FF%00%25E6%FE%FF%00%25F8%FE%FF%00%25E5
    Test URLEncoder.encode(userId,"UTF-16LE"): tester%25%00E6%25%00F8%25%00E5
    Test URLEncoder.encode(userId,"UTF-16BE"): tester%00%25E6%00%25F8%00%25E5
    Test engine.eval("encodeURIComponent(\""+userId+"\")"): tester%25E6%25F8%25E5
    Test encodeURIComponent(userId): tester%25E6%25F8%25E5
    TEST new URI(userId).toASCIIString(): tester%E6%F8%E5
    ------ END TESTING WITH USER ID = 'tester%E6%F8%E5' ----------------------

注意:当我写这篇文章时,我想到我可以使用URLEncoder.encode(userId,"UTF-8"),只要我在另一边使用了正确的解码器......但我还是在尝试找到一种方法对其进行编码以匹配JavaScript encodeURIComponent函数,该函数显然可以在不需要在另一侧解码的情况下工作.:)

mar*_*ard 5

根据Mozilla Developer Docs, encodeURICompoent()使用UTF-8进行编码.当我在你的绳子上运行时,我按预期得到测试者%C3%A6%C3%B8%C3%A5.当我运行以下Java代码时:

System.out.println(URLEncoder.encode("testeræøå", "UTF-8"));
Run Code Online (Sandbox Code Playgroud)

它还印刷测试剂%C3%A6%C3%B8%C3%A5.我也跑了你的考试,得到了:

    ------ START TESTING WITH USER ID = 'dummy' ----------------------
Test URLEncoder.encode(userId): dummy
Test URLEncoder.encode(userId,"UTF-8"): dummy
Test URLEncoder.encode(userId,"UTF-16"): dummy
Test URLEncoder.encode(userId,"UTF-16LE"): dummy
Test URLEncoder.encode(userId,"UTF-16BE"): dummy
Test engine.eval("encodeURIComponent(\""+userId+"\")"): dummy
Test encodeURIComponent(userId): dummy
TEST new URI(userId).toASCIIString(): dummy
------ END TESTING WITH USER ID = 'dummy' ----------------------


------ START TESTING WITH USER ID = 'testeræøå' ----------------------
Test URLEncoder.encode(userId): tester%C3%A6%C3%B8%C3%A5
Test URLEncoder.encode(userId,"UTF-8"): tester%C3%A6%C3%B8%C3%A5
Test URLEncoder.encode(userId,"UTF-16"): tester%FE%FF%00%E6%00%F8%00%E5
Test URLEncoder.encode(userId,"UTF-16LE"): tester%E6%00%F8%00%E5%00
Test URLEncoder.encode(userId,"UTF-16BE"): tester%00%E6%00%F8%00%E5
Test engine.eval("encodeURIComponent(\""+userId+"\")"): tester%C3%A6%C3%B8%C3%A5
Test encodeURIComponent(userId): tester%C3%A6%C3%B8%C3%A5
TEST new URI(userId).toASCIIString(): tester%C3%A6%C3%B8%C3%A5
------ END TESTING WITH USER ID = 'testeræøå' ----------------------


------ START TESTING WITH USER ID = 'tester%C3%A6%C3%B8%C3%A5' ----------------------
Test URLEncoder.encode(userId): tester%25C3%25A6%25C3%25B8%25C3%25A5
Test URLEncoder.encode(userId,"UTF-8"): tester%25C3%25A6%25C3%25B8%25C3%25A5
Test URLEncoder.encode(userId,"UTF-16"): tester%FE%FF%00%25C3%FE%FF%00%25A6%FE%FF%00%25C3%FE%FF%00%25B8%FE%FF%00%25C3%FE%FF%00%25A5
Test URLEncoder.encode(userId,"UTF-16LE"): tester%25%00C3%25%00A6%25%00C3%25%00B8%25%00C3%25%00A5
Test URLEncoder.encode(userId,"UTF-16BE"): tester%00%25C3%00%25A6%00%25C3%00%25B8%00%25C3%00%25A5
Test engine.eval("encodeURIComponent(\""+userId+"\")"): tester%25C3%25A6%25C3%25B8%25C3%25A5
Test encodeURIComponent(userId): tester%25C3%25A6%25C3%25B8%25C3%25A5
TEST new URI(userId).toASCIIString(): tester%C3%A6%C3%B8%C3%A5
------ END TESTING WITH USER ID = 'tester%C3%A6%C3%B8%C3%A5' ----------------------
Run Code Online (Sandbox Code Playgroud)

这就是我所期待的.

我认为您需要检查Java源文件的文件编码.如果您使用的是Eclipse,由于某种原因,它默认为cp1252.我安装Eclipse时所做的第一件事就是将默认编码更改为UTF-8.