如何让 Java 匹配 JavaScript encodeURIComponent() 方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25298063/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get Java to match JavaScript encodeURIComponent() method?
提问by mattssmith
I am trying to pass this strings in the URL which contain special characters and the only way I can get it to work is with JavaScript encodeURIComponent('tester???') which produces "tester%C3%A6%C3%B8%C3%A5"
我试图在包含特殊字符的 URL 中传递这个字符串,我可以让它工作的唯一方法是使用 JavaScript encodeURIComponent('tester???') 产生“ tester%C3%A6%C3%B8%C3 %A5"
Everything I try to do in Java produces different encodings, and do not work on the other end... Any idea how I can get tester??? encoded to tester%C3%A6%C3%B8%C3%A5 in Java? Thanks in advance!
我在 Java 中尝试做的所有事情都会产生不同的编码,并且在另一端不起作用......知道如何获得测试员吗???在 Java 中编码为 tester%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-_.!~*'()";
}
Output of above class is this:
上面的类的输出是这样的:
------ 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' ----------------------
Note: As I was writing this up, it occurred to me that I could use the URLEncoder.encode(userId, "UTF-8") as long as I used the proper decoder on the other side... but I was still trying to find a way to encode it to match the JavaScript encodeURIComponent function which apparently works without the need to decode it on the other side. :)
注意:在我写这篇文章的时候,我突然想到只要我在另一边使用了正确的解码器,我就可以使用 URLEncoder.encode(userId, "UTF-8") ......但我仍在尝试找到一种方法对其进行编码以匹配 JavaScript encodeURIComponent 函数,该函数显然无需在另一端解码即可工作。:)
回答by markbernard
According to Mozilla Developer DocsencodeURICompoent() uses UTF-8 to encode. When I run this on your string I get tester%C3%A6%C3%B8%C3%A5 as expected. When i run the following Java code:
根据Mozilla Developer DocsencodeURICompoent() 使用 UTF-8 进行编码。当我在你的字符串上运行这个时,我按预期得到了 tester%C3%A6%C3%B8%C3%A5 。当我运行以下 Java 代码时:
System.out.println(URLEncoder.encode("tester???", "UTF-8"));
It also prints tester%C3%A6%C3%B8%C3%A5. I also ran your test and got:
它还打印 tester%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' ----------------------
This is what I would expect.
这是我所期望的。
I think you need to check the file encoding for your Java source file. If you are using Eclipse it defaults to cp1252 for some reason. The first thing I do when I install Eclipse is change the default encoding to UTF-8.
我认为您需要检查 Java 源文件的文件编码。如果您使用 Eclipse,则出于某种原因,它默认为 cp1252。安装 Eclipse 时,我做的第一件事是将默认编码更改为 UTF-8。
回答by coding_idiot
For others stumbling upon this query & noticing that (space) translates to
+
in java but %20
in javascript.
对于其他人在此查询上绊倒并注意到(空格)转换为
+
java 但%20
在 javascript 中。
One possible solution is to use
org.apache.commons.httpclient.util.URIUtil#encodeQuery
一种可能的解决方案是使用
org.apache.commons.httpclient.util.URIUtil#encodeQuery
If you're using the latest httpclient 4, then
URIParserUtil#escapeChars
can be used instead.
如果您使用的是最新的 httpclient 4,则
URIParserUtil#escapeChars
可以改为使用。
Sample Code :
URIUtil.encodeQuery(strQuery); //httpclient 3.x
URIParserUtil.escapeChars(strQuery); //httpclient 4.x
示例代码:
URIUtil.encodeQuery(strQuery); //httpclient 3.x
URIParserUtil.escapeChars(strQuery); //httpclient 4.x