Saya telah bereksperimen dengan berbagai bit kode Java mencoba menghasilkan sesuatu yang akan menyandikan string yang berisi tanda kutip, spasi dan karakter Unicode "eksotis" dan menghasilkan keluaran yang identik dengan fungsi encodeURIComponent JavaScript .
String uji penyiksaan saya adalah: "A" B ± "
Jika saya memasukkan pernyataan JavaScript berikut di Firebug:
encodeURIComponent('"A" B ± "');
—Lalu saya mendapatkan:
"%22A%22%20B%20%C2%B1%20%22"
Inilah program Java tes kecil saya:
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class EncodingTest
{
public static void main(String[] args) throws UnsupportedEncodingException
{
String s = "\"A\" B ± \"";
System.out.println("URLEncoder.encode returns "
+ URLEncoder.encode(s, "UTF-8"));
System.out.println("getBytes returns "
+ new String(s.getBytes("UTF-8"), "ISO-8859-1"));
}
}
—Program ini menghasilkan:
URLEncoder.encode mengembalikan% 22A% 22 + B +% C2% B1 +% 22 getBytes mengembalikan "A" B ± "
Dekat, tapi tidak ada cerutu! Apa cara terbaik untuk menyandikan string UTF-8 menggunakan Java sehingga menghasilkan keluaran yang sama dengan JavaScript encodeURIComponent
?
EDIT: Saya menggunakan Java 1.4 segera pindah ke Java 5.
sumber
[~'()!]
artinya"~"
atau"'"
atau"("
atau")"
atau"!"
. :) Saya juga merekomendasikan untuk mempelajari dasar-dasar regex. (Saya juga tidak memperluasnya karena setidaknya dua jawaban lain menunjukkan kode Java masing-masing.)"+"
dengan"%20"
berpotensi merusak, seperti"+"
karakter legal di jalur URI (meskipun tidak dalam string kueri). Misalnya, "a + b c" harus dikodekan sebagai"a+b%20c"
; solusi ini akan mengubahnya menjadi"a%20b%20c"
. Sebagai gantinya, gunakannew URI(null, null, value, null).getRawPath()
.Ini adalah kelas yang saya dapatkan pada akhirnya:
import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; /** * Utility class for JavaScript compatible UTF-8 encoding and decoding. * * @see http://stackoverflow.com/questions/607176/java-equivalent-to-javascripts-encodeuricomponent-that-produces-identical-output * @author John Topley */ public class EncodingUtil { /** * Decodes the passed UTF-8 String using an algorithm that's compatible with * JavaScript's <code>decodeURIComponent</code> function. Returns * <code>null</code> if the String is <code>null</code>. * * @param s The UTF-8 encoded String to be decoded * @return the decoded String */ public static String decodeURIComponent(String s) { if (s == null) { return null; } String result = null; try { result = URLDecoder.decode(s, "UTF-8"); } // This exception should never occur. catch (UnsupportedEncodingException e) { result = s; } return result; } /** * Encodes the passed String as UTF-8 using an algorithm that's compatible * with JavaScript's <code>encodeURIComponent</code> function. Returns * <code>null</code> if the String is <code>null</code>. * * @param s The String to be encoded * @return the encoded String */ public static String encodeURIComponent(String s) { String result = null; try { result = URLEncoder.encode(s, "UTF-8") .replaceAll("\\+", "%20") .replaceAll("\\%21", "!") .replaceAll("\\%27", "'") .replaceAll("\\%28", "(") .replaceAll("\\%29", ")") .replaceAll("\\%7E", "~"); } // This exception should never occur. catch (UnsupportedEncodingException e) { result = s; } return result; } /** * Private constructor to prevent this class from being instantiated. */ private EncodingUtil() { super(); } }
sumber
%0A
yang berarti tombol kembali di input Android, atau akan membuat js crash."%0A"
? Karakter apa yang akan menjadi penggantinya? Apakah itu hanya string kosong""
?Menggunakan mesin javascript yang dikirimkan dengan Java 6:
import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; public class Wow { public static void main(String[] args) throws Exception { ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine engine = factory.getEngineByName("JavaScript"); engine.eval("print(encodeURIComponent('\"A\" B ± \"'))"); } }
Keluaran:% 22A% 22% 20B% 20% c2% b1% 20% 22
Kasusnya berbeda tetapi lebih dekat dengan apa yang Anda inginkan.
sumber
Saya menggunakan
java.net.URI#getRawPath()
, misalnyaString s = "a+b c.html"; String fixed = new URI(null, null, s, null).getRawPath();
Nilai
fixed
kemauana+b%20c.html
, yang Anda inginkan.Pasca-pemrosesan, output dari
URLEncoder.encode()
akan menghapus nilai tambah apa pun yang seharusnya ada di URI. Sebagai contohURLEncoder.encode("a+b c.html").replaceAll("\\+", "%20");
akan memberi Anda
a%20b%20c.html
, yang akan diartikan sebagaia b c.html
.sumber
http://a+b c.html
itu akan membuat kesalahanSaya datang dengan versi encodeURIComponent saya sendiri, karena solusi yang diposting memiliki satu masalah, jika ada + hadir dalam String, yang harus dikodekan, itu akan diubah menjadi spasi.
Jadi inilah kelasku:
import java.io.UnsupportedEncodingException; import java.util.BitSet; public final class EscapeUtils { /** used for the encodeURIComponent function */ private static final BitSet dontNeedEncoding; static { dontNeedEncoding = new BitSet(256); // a-z for (int i = 97; i <= 122; ++i) { dontNeedEncoding.set(i); } // A-Z for (int i = 65; i <= 90; ++i) { dontNeedEncoding.set(i); } // 0-9 for (int i = 48; i <= 57; ++i) { dontNeedEncoding.set(i); } // '()* for (int i = 39; i <= 42; ++i) { dontNeedEncoding.set(i); } dontNeedEncoding.set(33); // ! dontNeedEncoding.set(45); // - dontNeedEncoding.set(46); // . dontNeedEncoding.set(95); // _ dontNeedEncoding.set(126); // ~ } /** * A Utility class should not be instantiated. */ private EscapeUtils() { } /** * Escapes all characters except the following: alphabetic, decimal digits, - _ . ! ~ * ' ( ) * * @param input * A component of a URI * @return the escaped URI component */ public static String encodeURIComponent(String input) { if (input == null) { return input; } StringBuilder filtered = new StringBuilder(input.length()); char c; for (int i = 0; i < input.length(); ++i) { c = input.charAt(i); if (dontNeedEncoding.get(c)) { filtered.append(c); } else { final byte[] b = charToBytesUTF(c); for (int j = 0; j < b.length; ++j) { filtered.append('%'); filtered.append("0123456789ABCDEF".charAt(b[j] >> 4 & 0xF)); filtered.append("0123456789ABCDEF".charAt(b[j] & 0xF)); } } } return filtered.toString(); } private static byte[] charToBytesUTF(char c) { try { return new String(new char[] { c }).getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { return new byte[] { (byte) c }; } } }
sumber
URLEncoder.encode("+", "UTF-8");
hasil"%2B"
, yang merupakan pengkodean URL yang tepat, jadi solusi Anda, maaf, sama sekali tidak perlu. Mengapa di bumiURLEncoder.encode
tidak mengubah ruang menjadi%20
berada di luar jangkauan saya.Saya menemukan implementasi lain yang didokumentasikan di, http://blog.sangupta.com/2010/05/encodeuricomponent-and.html . Implementasinya juga dapat menangani byte Unicode.
sumber
Saya telah berhasil menggunakan kelas java.net.URI seperti:
public static String uriEncode(String string) { String result = string; if (null != string) { try { String scheme = null; String ssp = string; int es = string.indexOf(':'); if (es > 0) { scheme = string.substring(0, es); ssp = string.substring(es + 1); } result = (new URI(scheme, ssp, null)).toString(); } catch (URISyntaxException usex) { // ignore and use string that has syntax error } } return result; }
sumber
Ini adalah contoh langsung solusi Ravi Wallau:
public String buildSafeURL(String partialURL, String documentName) throws ScriptException { ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); ScriptEngine scriptEngine = scriptEngineManager .getEngineByName("JavaScript"); String urlSafeDocumentName = String.valueOf(scriptEngine .eval("encodeURIComponent('" + documentName + "')")); String safeURL = partialURL + urlSafeDocumentName; return safeURL; } public static void main(String[] args) { EncodeURIComponentDemo demo = new EncodeURIComponentDemo(); String partialURL = "https://www.website.com/document/"; String documentName = "Tom & Jerry Manuscript.pdf"; try { System.out.println(demo.buildSafeURL(partialURL, documentName)); } catch (ScriptException se) { se.printStackTrace(); } }
Keluaran:
https://www.website.com/document/Tom%20%26%20Jerry%20Manuscript.pdf
Ini juga menjawab pertanyaan gantung di komentar oleh Loren Shqipognja tentang cara meneruskan variabel String ke
encodeURIComponent()
. Metode iniscriptEngine.eval()
mengembalikanObject
, sehingga dapat dikonversi ke String melalui diString.valueOf()
antara metode lainnya.sumber
bagi saya ini berhasil:
import org.apache.http.client.utils.URIBuilder; String encodedString = new URIBuilder() .setParameter("i", stringToEncode) .build() .getRawQuery() // output: i=encodedString .substring(2);
atau dengan UriBuilder yang berbeda
import javax.ws.rs.core.UriBuilder; String encodedString = UriBuilder.fromPath("") .queryParam("i", stringToEncode) .toString() // output: ?i=encodedString .substring(3);
Menurut pendapat saya, menggunakan pustaka standar adalah ide yang lebih baik daripada pemrosesan pos secara manual. Juga jawaban @Chris tampak bagus, tetapi tidak berfungsi untuk url, seperti " http: // a + b c.html"
sumber
encodeURIComponent
.encodeURIComponent
kembali untuk?&
hasilnya%3F%26%20
, tetapi saran Anda kembali%3F%26+
. Saya tahu ini disebutkan beberapa kali dalam pertanyaan dan jawaban lain, tetapi harus disebutkan di sini, sebelum orang mempercayainya.Inilah yang saya gunakan:
private static final String HEX = "0123456789ABCDEF"; public static String encodeURIComponent(String str) { if (str == null) return null; byte[] bytes = str.getBytes(StandardCharsets.UTF_8); StringBuilder builder = new StringBuilder(bytes.length); for (byte c : bytes) { if (c >= 'a' ? c <= 'z' || c == '~' : c >= 'A' ? c <= 'Z' || c == '_' : c >= '0' ? c <= '9' : c == '-' || c == '.') builder.append((char)c); else builder.append('%') .append(HEX.charAt(c >> 4 & 0xf)) .append(HEX.charAt(c & 0xf)); } return builder.toString(); }
Ini melampaui Javascript dengan persen-encoding setiap karakter yang bukan merupakan karakter yang tidak dicadangkan menurut RFC 3986 .
Ini adalah konversi yang berlawanan:
public static String decodeURIComponent(String str) { if (str == null) return null; int length = str.length(); byte[] bytes = new byte[length / 3]; StringBuilder builder = new StringBuilder(length); for (int i = 0; i < length; ) { char c = str.charAt(i); if (c != '%') { builder.append(c); i += 1; } else { int j = 0; do { char h = str.charAt(i + 1); char l = str.charAt(i + 2); i += 3; h -= '0'; if (h >= 10) { h |= ' '; h -= 'a' - '0'; if (h >= 6) throw new IllegalArgumentException(); h += 10; } l -= '0'; if (l >= 10) { l |= ' '; l -= 'a' - '0'; if (l >= 6) throw new IllegalArgumentException(); l += 10; } bytes[j++] = (byte)(h << 4 | l); if (i >= length) break; c = str.charAt(i); } while (c == '%'); builder.append(new String(bytes, 0, j, UTF_8)); } } return builder.toString(); }
sumber
Saya telah menemukan kelas PercentEscaper dari pustaka google-http-java-client, yang dapat digunakan untuk mengimplementasikan encodeURIComponent dengan cukup mudah.
PercentEscaper dari beranda google-http-java-client javadoc google-http-java-client
sumber
Perpustakaan jambu biji memiliki PercentEscaper:
Escaper percentEscaper = new PercentEscaper("-_.*", false);
"-_. *" adalah karakter aman
false mengatakan PercentEscaper untuk keluar dari spasi dengan '% 20', bukan '+'
sumber
Saya biasa
String encodedUrl = new URI(null, url, null).toASCIIString();
menyandikan url. Untuk menambah parameter setelah yang ada diurl
saya gunakanUriComponentsBuilder
sumber